Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
GeometryPrimitives.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
33 #include <vlGraphics/Geometry.hpp>
36 
37 using namespace vl;
38 
39 //-----------------------------------------------------------------------------
42 ref<Geometry> vl::makeIcosphere(const vec3& pos, real diameter, int detail, bool remove_doubles)
43 {
44  ref<Geometry> geom = new Geometry;
45  geom->setObjectName("Icosphere");
46 
47  ref<ArrayFloat3> coords = new ArrayFloat3;
48  ref<ArrayFloat3> norms = new ArrayFloat3;
49 
51 
52  const real X = (real)0.525731112119133606;
53  const real Z = (real)0.850650808352039932;
54  std::vector< vec3 > verts;
55  verts.push_back( vec3(-X, 0, Z) );
56  verts.push_back( vec3(X, 0, Z) );
57  verts.push_back( vec3(-X, 0, -Z) );
58  verts.push_back( vec3(X, 0, -Z) );
59  verts.push_back( vec3(0, Z, X) );
60  verts.push_back( vec3(0, Z, -X) );
61  verts.push_back( vec3(0, -Z, X) );
62  verts.push_back( vec3(0, -Z, -X) );
63  verts.push_back( vec3(Z, X, 0) );
64  verts.push_back( vec3(-Z, X, 0) );
65  verts.push_back( vec3(Z, -X, 0) );
66  verts.push_back( vec3(-Z, -X, 0) );
67 
68  int idxs[] = {
69  1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4,
70  1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2,
71  3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0,
72  10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7
73  };
74 
75  std::vector<int> indices;
76  for(int i=0; i<4*5*3; ++i)
77  indices.push_back(idxs[i]);
78 
79  // triangulate the icosahedron
80  if (detail>8)
81  detail = 8;
82  if (detail<0)
83  detail = 0;
84  for(int i=0; i<detail; ++i)
85  {
86  std::vector<int> indices2;
87  std::vector< vec3 > verts2;
88  for( int j=0, idx=0; j<(int)indices.size(); j+=3)
89  {
90  indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
91  indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
92  indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
93  indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++);
94 
95  vec3 v1 = verts[ indices[j+0] ]; v1.normalize();
96  vec3 v2 = verts[ indices[j+1] ]; v2.normalize();
97  vec3 v3 = verts[ indices[j+2] ]; v3.normalize();
98  vec3 a = (v1 + v2) * 0.5f; a.normalize();
99  vec3 b = (v2 + v3) * 0.5f; b.normalize();
100  vec3 c = (v3 + v1) * 0.5f; c.normalize();
101  verts2.push_back(v1); verts2.push_back( a); verts2.push_back(c);
102  verts2.push_back( a); verts2.push_back(v2); verts2.push_back(b);
103  verts2.push_back( a); verts2.push_back( b); verts2.push_back(c);
104  verts2.push_back( c); verts2.push_back( b); verts2.push_back(v3);
105  }
106  verts = verts2;
107  indices = indices2;
108  }
109 
110  // generate sphere vertices and connection information
111 
112  real radius = diameter / 2;
113 
114  coords->resize( (int)verts.size() );
115  norms->resize( (int)verts.size() );
116  for( int i=0; i<(int)verts.size(); ++i )
117  {
118  coords->at(i) = (fvec3)(verts[i]*radius + pos);
119  vec3 n = verts[i];
120  n.normalize();
121  norms->at(i) = (fvec3)n;
122  }
123 
124  polys->indexBuffer()->resize( (int)indices.size() );
125  for(int i=0; i<(int)indices.size(); ++i)
126  {
127  VL_CHECK( indices[i] < (int)coords->size() )
128  polys->indexBuffer()->at(i) = indices[i];
129  }
130 
131  geom->setVertexArray(coords.get());
132  geom->setNormalArray(norms.get());
133  geom->drawCalls().push_back(polys.get());
134 
135  if (remove_doubles)
136  {
138  dvr.removeDoubles(geom.get());
139  }
140 
141 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
142  geom->makeGLESFriendly();
143 #endif
144 
145  return geom;
146 }
147 //-----------------------------------------------------------------------------
148 ref<Geometry> vl::makeTeapot( const vec3& origin, real diameter, int detail)
149 {
150  // 32 patches 4x4
151  static const int patch_idx[] = {
152  1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
153  4, 17, 18, 19, 8, 20, 21, 22, 12, 23, 24, 25, 16, 26, 27, 28,
154  19, 29, 30, 31, 22, 32, 33, 34, 25, 35, 36, 37, 28, 38, 39, 40,
155  31, 41, 42, 1, 34, 43, 44, 5, 37, 45, 46, 9, 40, 47, 48, 13,
156  13, 14, 15, 16, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
157  16, 26, 27, 28, 52, 61, 62, 63, 56, 64, 65, 66, 60, 67, 68, 69,
158  28, 38, 39, 40, 63, 70, 71, 72, 66, 73, 74, 75, 69, 76, 77, 78,
159  40, 47, 48, 13, 72, 79, 80, 49, 75, 81, 82, 53, 78, 83, 84, 57,
160  57, 58, 59, 60, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
161  60, 67, 68, 69, 88, 97, 98, 99, 92, 100, 101, 102, 96, 103, 104, 105,
162  69, 76, 77, 78, 99, 106, 107, 108, 102, 109, 110, 111, 105, 112, 113, 114,
163  78, 83, 84, 57, 108, 115, 116, 85, 111, 117, 118, 89, 114, 119, 120, 93,
164  121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
165  124, 137, 138, 121, 128, 139, 140, 125, 132, 141, 142, 129, 136, 143, 144, 133,
166  133, 134, 135, 136, 145, 146, 147, 148, 149, 150, 151, 152, 69, 153, 154, 155,
167  136, 143, 144, 133, 148, 156, 157, 145, 152, 158, 159, 149, 155, 160, 161, 69,
168  162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177,
169  165, 178, 179, 162, 169, 180, 181, 166, 173, 182, 183, 170, 177, 184, 185, 174,
170  174, 175, 176, 177, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197,
171  177, 184, 185, 174, 189, 198, 199, 186, 193, 200, 201, 190, 197, 202, 203, 194,
172  204, 204, 204, 204, 207, 208, 209, 210, 211, 211, 211, 211, 212, 213, 214, 215,
173  204, 204, 204, 204, 210, 217, 218, 219, 211, 211, 211, 211, 215, 220, 221, 222,
174  204, 204, 204, 204, 219, 224, 225, 226, 211, 211, 211, 211, 222, 227, 228, 229,
175  204, 204, 204, 204, 226, 230, 231, 207, 211, 211, 211, 211, 229, 232, 233, 212,
176  212, 213, 214, 215, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
177  215, 220, 221, 222, 237, 246, 247, 248, 241, 249, 250, 251, 245, 252, 253, 254,
178  222, 227, 228, 229, 248, 255, 256, 257, 251, 258, 259, 260, 254, 261, 262, 263,
179  229, 232, 233, 212, 257, 264, 265, 234, 260, 266, 267, 238, 263, 268, 269, 242,
180  270, 270, 270, 270, 279, 280, 281, 282, 275, 276, 277, 278, 271, 272, 273, 274,
181  270, 270, 270, 270, 282, 289, 290, 291, 278, 286, 287, 288, 274, 283, 284, 285,
182  270, 270, 270, 270, 291, 298, 299, 300, 288, 295, 296, 297, 285, 292, 293, 294,
183  270, 270, 270, 270, 300, 305, 306, 279, 297, 303, 304, 275, 294, 301, 302, 271
184  };
185 
186  // 306 vertex coordinates
187  static const float coords[] = {
188  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,
189  1.3375f, -0.749f, 2.53125f, 0.749f, -1.3375f, 2.53125f, 0.0f, -1.3375f, 2.53125f, 1.4375f, 0.0f, 2.53125f,
190  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,
191  -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,
192  0.0f, 2.4f, -0.749f, -1.3375f, 2.53125f, -1.3375f, -0.749f, 2.53125f, -1.3375f, 0.0f, 2.53125f, -0.805f,
193  -1.4375f, 2.53125f, -1.4375f, -0.805f, 2.53125f, -1.4375f, 0.0f, 2.53125f, -0.84f, -1.5f, 2.4f, -1.5f,
194  -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,
195  0.749f, 2.53125f, -0.749f, 1.3375f, 2.53125f, 0.0f, 1.3375f, 2.53125f, -1.4375f, 0.805f, 2.53125f, -0.805f,
196  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,
197  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,
198  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,
199  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,
200  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,
201  -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,
202  -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,
203  -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,
204  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,
205  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,
206  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,
207  -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,
208  -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,
209  -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,
210  -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,
211  -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,
212  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,
213  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,
214  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,
215  -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,
216  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,
217  -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,
218  -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,
219  -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,
220  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,
221  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,
222  -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,
223  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,
224  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,
225  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,
226  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,
227  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,
228  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,
229  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,
230  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,
231  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,
232  -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,
233  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,
234  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,
235  -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,
236  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,
237  -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,
238  -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,
239  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,
240  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,
241  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,
242  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,
243  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,
244  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,
245  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,
246  -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,
247  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,
248  -0.798f, 0.0f
249  };
250 
251  ref<BezierSurface> teapot = new BezierSurface;
252  const fvec3* verts = (const fvec3*)coords;
253 
254  for(int i=0; i<32; ++i)
255  {
256  ref<BezierPatch> patch = new BezierPatch(4,4);
257  for(int j=0; j<16; ++j)
258  {
259  int idx = patch_idx[j+16*i]-1;
260  VL_CHECK(idx < sizeof(coords) / coords[0])
261  patch->points()[j] = (vec3)verts[ idx ];
262  }
263  teapot->patches().push_back(patch.get());
264  }
265  teapot->setDetail(detail);
266  teapot->updateBezierSurface(false);
267  real s = real(1.0) / teapot->boundingBox().width() * diameter;
268  mat4 m = mat4::getTranslation( origin ) *
269  mat4::getRotation(-90, 1, 0, 0) *
270  mat4::getScaling(s, s, s) *
272  teapot->transform( m );
273 
275  dvr.removeDoubles(teapot.get());
276 
277 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
278  teapot->makeGLESFriendly();
279 #endif
280 
281  return teapot;
282 }
283 //-----------------------------------------------------------------------------
284 ref<Geometry> vl::makeUVSphere( const vec3& origin, real diameter, int phi, int theta)
285 {
286  ref<Geometry> geom = new Geometry;
287  geom->setObjectName("UVSphere");
288 
289  diameter = diameter / 2.0f;
290  ref<ArrayFloat3> vert3 = new ArrayFloat3;
291  geom->setVertexArray(vert3.get());
292 
293  // create vertices
294  vert3->resize( theta * phi + 2 );
295  int vert_idx=0;
296  vert3->at(vert_idx++) = (fvec3)(vec3(0,1*diameter,0) + origin);
297  for(int i=0; i<theta; ++i)
298  {
299  for(int j=0; j<phi; ++j)
300  {
301  // vec3 v(1*radius,radius - radius*2*((real)i/(theta-1)),0);
302  vec3 v(0,1*diameter,0);
303  v = mat4::getRotation(180.0f/(theta+1)*(i+1),0,0,1) * v;
304  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
305  vert3->at(vert_idx++) = (fvec3)(v+origin);
306  }
307  }
308  vert3->at(vert_idx++) = (fvec3)(vec3(0,-1*diameter,0) + origin);
309 
310  // side quads
311 
313  quads->indexBuffer()->resize( (theta-1)*phi*4 );
314  geom->drawCalls().push_back(quads.get());
315  int idx = 0;
316  for(int i=0; i<theta-1; ++i)
317  {
318  for(int j=0; j<phi; ++j)
319  {
320  quads->indexBuffer()->at(idx++) = 1+phi*(i+1)+(j+0)%phi;
321  quads->indexBuffer()->at(idx++) = 1+phi*(i+1)+(j+1)%phi;
322  quads->indexBuffer()->at(idx++) = 1+phi*(i+0)+(j+1)%phi;
323  quads->indexBuffer()->at(idx++) = 1+phi*(i+0)+(j+0)%phi;
324  }
325  }
326 
327  // top/bottom triangles
328 
330 
331  tris->indexBuffer()->resize( phi*3 + phi*3 );
332  geom->drawCalls().push_back(tris.get());
333  idx = 0;
334  // top fan
335  for(int j=0; j<phi; ++j)
336  {
337  tris->indexBuffer()->at(idx++) = 0;
338  tris->indexBuffer()->at(idx++) = 1+(j+0)%phi;
339  tris->indexBuffer()->at(idx++) = 1+(j+1)%phi;
340  }
341  // bottom fan
342  for(int j=0; j<phi; ++j)
343  {
344  tris->indexBuffer()->at(idx++) = (int)geom->vertexArray()->size()-1;
345  tris->indexBuffer()->at(idx++) = 1+phi*(theta-1)+(j+1)%phi;
346  tris->indexBuffer()->at(idx++) = 1+phi*(theta-1)+(j+0)%phi;
347  }
348 
349 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
350  geom->makeGLESFriendly();
351 #endif
352 
353  return geom;
354 }
355 //-----------------------------------------------------------------------------
356 ref<Geometry> vl::makeCylinder( const vec3& origin, real diameter, real height, int phi, int theta, bool top, bool bottom)
357 {
358  ref<Geometry> geom = new Geometry;
359  geom->setObjectName("Cylinder");
360 
361  diameter = diameter / 2;
362  height = height / 2;
363  ref<ArrayFloat3> vert3 = new ArrayFloat3;
364  geom->setVertexArray(vert3.get());
365 
366  // create vertices
367  vert3->resize( theta * phi + (top?phi+1:0) + (bottom?phi+1:0) );
368  int vert_idx=0;
369  for(int i=0; i<theta; ++i)
370  {
371  for(int j=0; j<phi; ++j)
372  {
373  vec3 v(1*diameter, 1*height - 2*height*((real)i/(theta-1)), 0);
374  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
375  vert3->at(vert_idx++) = (fvec3)(v + origin);
376  }
377  }
378 
379  // side quads
380 
382  quads->indexBuffer()->resize( (theta-1)*phi*4 );
383  geom->drawCalls().push_back(quads.get());
384  int idx = 0;
385  for(int i=0; i<theta-1; ++i)
386  {
387  for(int j=0; j<phi; ++j)
388  {
389  quads->indexBuffer()->at(idx++) = phi*(i+1)+(j+0)%phi;
390  quads->indexBuffer()->at(idx++) = phi*(i+1)+(j+1)%phi;
391  quads->indexBuffer()->at(idx++) = phi*(i+0)+(j+1)%phi;
392  quads->indexBuffer()->at(idx++) = phi*(i+0)+(j+0)%phi;
393  }
394  }
395 
396  // top/bottom triangles
397 
398  if (top)
399  {
401  tris->indexBuffer()->resize( phi+2 );
402  geom->drawCalls().push_back(tris.get());
403  idx = 0;
404 
405  int fan_center = vert_idx;
406  vert3->at(vert_idx++) = (fvec3)(vec3(0, height, 0) + origin);
407  for(int j=0; j<phi; ++j)
408  {
409  vec3 v(1*diameter, height, 0);
410  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
411  vert3->at(vert_idx++) = (fvec3)(v + origin);
412  }
413 
414  // top fan
415  tris->indexBuffer()->at(idx++) = fan_center;
416  for(int j=0; j<phi+1; ++j)
417  tris->indexBuffer()->at(idx++) = 1+fan_center+j%phi;
418  }
419 
420  if (bottom)
421  {
423  tris->indexBuffer()->resize( phi+2 );
424  geom->drawCalls().push_back(tris.get());
425  idx = 0;
426 
427  int fan_center = vert_idx;
428  vert3->at(vert_idx++) = (fvec3)(vec3(0, -height, 0) + origin);
429  for(int j=0; j<phi; ++j)
430  {
431  vec3 v(1*diameter, - height, 0);
432  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
433  vert3->at(vert_idx++) = (fvec3)(v + origin);
434  }
435 
436  // bottom fan
437  tris->indexBuffer()->at(idx++) = fan_center;
438  for(int j=0; j<phi+1; ++j)
439  tris->indexBuffer()->at(idx++) = 1+fan_center+(phi -1 - j%phi);
440  }
441 
442 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
443  geom->makeGLESFriendly();
444 #endif
445 
446  return geom;
447 }
448 //-----------------------------------------------------------------------------
449 ref<Geometry> vl::makeTorus( const vec3& origin, real diameter, real thickness, int phi, int theta, float tex_coords )
450 {
451  ref<Geometry> geom = new Geometry;
452  geom->setObjectName("Torus");
453 
454  // create vertices
455  thickness /= 2.0f;
456  const real radius = diameter / 2.0f - thickness;
457 
458  // vertices
459  ref<ArrayFloat3> vert3 = new ArrayFloat3;
460  geom->setVertexArray(vert3.get());
461  vert3->resize( (phi+1) * (theta+1) );
462 
463  // normals
464  ref<ArrayFloat3> norm3 = new ArrayFloat3;
465  geom->setNormalArray(norm3.get());
466  norm3->resize( (phi+1) * (theta+1) );
467 
468  // texture coordinates
469  ref<ArrayFloat2> texc2 = new ArrayFloat2;
470  if (tex_coords)
471  {
472  geom->setTexCoordArray(0,texc2.get());
473  texc2->resize( (phi+1) * (theta+1) );
474  }
475 
476  int vect_idx = 0;
477  for(int i=0; i<theta+1; ++i)
478  {
479  for(int j=0; j<phi+1; ++j)
480  {
481  vec3 v(thickness, 0, 0);
482  vec3 o(radius, 0, 0);
483  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
484  v = mat4::getRotation(360.0f/theta*i,0,0,1) * v;
485  o = mat4::getRotation(360.0f/theta*i,0,0,1) * o;
486 
487  if (tex_coords)
488  texc2->at(vect_idx) = fvec2((float)i/theta,(float)j/phi) * tex_coords;
489 
490  vert3->at(vect_idx) = (fvec3)(v + o + origin);
491 
492  norm3->at(vect_idx) = (fvec3)v.normalize();
493 
494  ++vect_idx;
495  }
496  }
497 
499  geom->drawCalls().push_back(polys.get());
500  int idx = 0;
501  polys->indexBuffer()->resize( theta * phi * 4 );
502  // create indices
503  for(int i=0; i<theta; ++i)
504  {
505  for(int j=0; j<phi; ++j)
506  {
507  int i1 = i+1;
508  polys->indexBuffer()->at(idx++) = (phi+1)*i +(j+0);
509  polys->indexBuffer()->at(idx++) = (phi+1)*i +(j+1);
510  polys->indexBuffer()->at(idx++) = (phi+1)*i1+(j+1);
511  polys->indexBuffer()->at(idx++) = (phi+1)*i1+(j+0);
512  }
513  }
514 
515 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
516  geom->makeGLESFriendly();
517 #endif
518 
519  return geom;
520 }
521 //-----------------------------------------------------------------------------
522 ref<Geometry> vl::makeBox( const AABB& aabb, bool tex_coords )
523 {
524  return makeBox( aabb.minCorner(), aabb.maxCorner(), tex_coords );
525 }
526 //-----------------------------------------------------------------------------
527 ref<Geometry> vl::makeBox( const vec3& min, const vec3& max, bool tex_coords )
528 {
529  return makeBox( (min+max)*0.5, max.x()-min.x(), max.y()-min.y(), max.z()-min.z(), tex_coords );
530 }
531 //-----------------------------------------------------------------------------
532 ref<Geometry> vl::makeBox( const vec3& origin, real xside, real yside, real zside, bool tex_coords)
533 {
534  /*
535  1--------0
536  |\ |\
537  | 5------|-4
538  2--------3 |
539  \| \|
540  6------- 7
541  */
542 
543  ref<Geometry> geom = new Geometry;
544  geom->setObjectName("Box");
545 
546  ref<ArrayFloat3> vert3 = new ArrayFloat3;
547  geom->setVertexArray(vert3.get());
548 
549  real x=xside/2.0f;
550  real y=yside/2.0f;
551  real z=zside/2.0f;
552 
553  fvec3 a0( (fvec3)(vec3(+x,+y,+z) + origin) );
554  fvec3 a1( (fvec3)(vec3(-x,+y,+z) + origin) );
555  fvec3 a2( (fvec3)(vec3(-x,-y,+z) + origin) );
556  fvec3 a3( (fvec3)(vec3(+x,-y,+z) + origin) );
557  fvec3 a4( (fvec3)(vec3(+x,+y,-z) + origin) );
558  fvec3 a5( (fvec3)(vec3(-x,+y,-z) + origin) );
559  fvec3 a6( (fvec3)(vec3(-x,-y,-z) + origin) );
560  fvec3 a7( (fvec3)(vec3(+x,-y,-z) + origin) );
561 
562 #if defined(VL_OPENGL)
563 
564  fvec3 verts[] = {
565  a1, a2, a3, a0,
566  a2, a6, a7, a3,
567  a6, a5, a4, a7,
568  a5, a1, a0, a4,
569  a0, a3, a7, a4,
570  a5, a6, a2, a1
571  };
572 
573  ref<DrawArrays> polys = new DrawArrays(PT_QUADS, 0, 24);
574  geom->drawCalls().push_back( polys.get() );
575  vert3->resize( 24 );
576  memcpy(vert3->ptr(), verts, sizeof(verts));
577 
578  if(tex_coords)
579  {
580  fvec2 texc[] = {
581  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
582  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
583  fvec2(1,0), fvec2(1,1), fvec2(0,1), fvec2(0,0),
584  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,1),
585  fvec2(0,0), fvec2(1,0), fvec2(1,1), fvec2(0,1),
586  fvec2(1,1), fvec2(0,1), fvec2(0,0), fvec2(1,0)
587  };
588  ref<ArrayFloat2> tex_array = new ArrayFloat2;
589  geom->setTexCoordArray(0, tex_array.get());
590  tex_array->resize( vert3->size() );
591  memcpy(tex_array->ptr(), texc, sizeof(texc));
592  }
593 
594 #else
595 
596  fvec3 verts[] = {
597  a1, a2, a3, a3, a0, a1,
598  a2, a6, a7, a7, a3, a2,
599  a6, a5, a4, a4, a7, a6,
600  a5, a1, a0, a0, a4, a5,
601  a0, a3, a7, a7, a4, a0,
602  a5, a6, a2, a2, a1, a5
603  };
604 
605  ref<DrawArrays> polys = new DrawArrays(PT_TRIANGLES, 0, 36);
606  geom->drawCalls().push_back( polys.get() );
607  vert3->resize( 36 );
608  memcpy(vert3->ptr(), verts, sizeof(verts));
609 
610  if(tex_coords)
611  {
612  fvec2 texc[] = {
613  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1),
614  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1),
615  fvec2(1,0), fvec2(1,1), fvec2(0,1), fvec2(0,1), fvec2(0,0), fvec2(1,0),
616  fvec2(0,1), fvec2(0,0), fvec2(1,0), fvec2(1,0), fvec2(1,1), fvec2(0,1),
617  fvec2(0,0), fvec2(1,0), fvec2(1,1), fvec2(1,1), fvec2(0,1), fvec2(0,0),
618  fvec2(1,1), fvec2(0,1), fvec2(0,0), fvec2(0,0), fvec2(1,0), fvec2(1,1),
619  };
620  ref<ArrayFloat2> tex_array = new ArrayFloat2;
621  geom->setTexCoordArray(0, tex_array.get());
622  tex_array->resize( vert3->size() );
623  memcpy(tex_array->ptr(), texc, sizeof(texc));
624  }
625 
626 #endif
627 
628 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
629  geom->makeGLESFriendly();
630 #endif
631 
632  return geom;
633 }
634 //-----------------------------------------------------------------------------
635 ref<Geometry> vl::makePyramid( const vec3& origin, real side, real height)
636 {
637  ref<Geometry> geom = new Geometry;
638  geom->setObjectName("Pyramid");
639 
640  ref<ArrayFloat3> vert3 = new ArrayFloat3;
641  geom->setVertexArray(vert3.get());
642 
643  real x = side / 2.0f;
644  real y = height;
645  real z = side / 2.0f;
646 
647  fvec3 a0( (fvec3)(vec3(+0,+y,+0) + origin) );
648  fvec3 a1( (fvec3)(vec3(-x,+0,-z) + origin) );
649  fvec3 a2( (fvec3)(vec3(-x,-0,+z) + origin) );
650  fvec3 a3( (fvec3)(vec3(+x,-0,+z) + origin) );
651  fvec3 a4( (fvec3)(vec3(+x,+0,-z) + origin) );
652 
653  ref<DrawArrays> polys = new DrawArrays(PT_TRIANGLES, 0, 6*3);
654  geom->drawCalls().push_back( polys.get() );
655 
656  vert3->resize(6*3);
657 
658  vert3->at(0) = a4; vert3->at(1) = a2; vert3->at(2) = a1;
659  vert3->at(3) = a2; vert3->at(4) = a4; vert3->at(5) = a3;
660  vert3->at(6) = a4; vert3->at(7) = a1; vert3->at(8) = a0;
661  vert3->at(9) = a1; vert3->at(10) = a2; vert3->at(11) = a0;
662  vert3->at(12) = a2; vert3->at(13) = a3; vert3->at(14) = a0;
663  vert3->at(15) = a3; vert3->at(16) = a4; vert3->at(17) = a0;
664 
665 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
666  geom->makeGLESFriendly();
667 #endif
668 
669  return geom;
670 }
671 //-----------------------------------------------------------------------------
672 ref<Geometry> vl::makeCone( const vec3& origin, real diameter, real height, int phi, bool bottom)
673 {
674  ref<Geometry> geom = new Geometry;
675  geom->setObjectName("Cone");
676 
677  ref<ArrayFloat3> vert3 = new ArrayFloat3;
678  geom->setVertexArray( vert3.get() );
679 
680  diameter = diameter / 2;
681 
682  vert3->resize( phi+1 + (bottom?phi+1:0) );
683  // create vertices
684  int vert_idx = 0;
685  vert3->at(vert_idx++) = (fvec3)(vec3(0, height/2.0f, 0) + origin);
686  for(int j=0; j<phi; ++j)
687  {
688  vec3 v(1*diameter, -height/2.0f, 0);
689  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
690  vert3->at(vert_idx++) = (fvec3)(v + origin);
691  }
692 
693  // top fan
695  top_fan->indexBuffer()->resize(phi+2);
696  geom->drawCalls().push_back(top_fan.get());
697  int idx = 0;
698  top_fan->indexBuffer()->at(idx++) = 0;
699  for(int j=0; j<phi+1; ++j)
700  top_fan->indexBuffer()->at(idx++) = 1+j%phi;
701 
702  // bottom fan
703  if (bottom)
704  {
705  int fan_center = vert_idx;
706  vert3->at(vert_idx++) = (fvec3)(vec3(0, -height/2.0f, 0) + origin);
707  for(int j=0; j<phi; ++j)
708  {
709  vec3 v(1*diameter, -height/2.0f, 0);
710  v = mat4::getRotation(360.0f/phi*j,0,1,0) * v;
711  vert3->at(vert_idx++) = (fvec3)(v + origin);
712  }
713 
715  bottom_fan->indexBuffer()->resize(phi+2);
716  geom->drawCalls().push_back(bottom_fan.get());
717  idx = 0;
718  bottom_fan->indexBuffer()->at(idx++) = fan_center;
719  for(int j=0; j<phi+1; ++j)
720  bottom_fan->indexBuffer()->at(idx++) = fan_center+1+(phi-1-j%phi);
721  }
722 
723 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
724  geom->makeGLESFriendly();
725 #endif
726 
727  return geom;
728 }
729 //-----------------------------------------------------------------------------
731 ref<Geometry> vl::makeGrid( const vec3& origin, real xside, real zside, int x, int z, bool gen_texcoords, fvec2 uv0, fvec2 uv1, bool center)
732 {
733  ref<Geometry> geom = new Geometry;
734  geom->setObjectName("Grid");
735 
736  ref<ArrayFloat3> vert3 = new ArrayFloat3;
737  ref<ArrayFloat2> text2 = new ArrayFloat2;
738  geom->setVertexArray( vert3.get() );
739 
740  VL_CHECK(x>=2)
741  VL_CHECK(z>=2)
742  real dx = xside / (x-1);
743  real dz = zside / (z-1);
744  if (center) {
745  xside /= 2.0f;
746  zside /= 2.0f;
747  }
748 
749  vert3->resize( x * z );
750  if (gen_texcoords)
751  {
752  geom->setTexCoordArray( 0, text2.get() );
753  text2->resize( x * z );
754  }
755 
756  // create vertices
757  int vert_idx = 0;
758  for(int i=0; i<z; ++i)
759  for(int j=0; j<x; ++j, ++vert_idx)
760  {
761  vert3->at(vert_idx) = (fvec3)(vec3(-xside+j*dx, 0, -zside+i*dz) + origin);
762  if (gen_texcoords)
763  {
764  float tu = (float)j/(x-1); // 0 .. 1
765  float tv = (float)i/(z-1); // 0 .. 1
766  text2->at(vert_idx).s() = (1.0f-tu) * uv0.s() + tu * uv1.s();
767  text2->at(vert_idx).t() = (1.0f-tv) * uv0.t() + tv * uv1.t();
768  }
769  }
770 
771  // create indices
773  geom->drawCalls().push_back(polys.get());
774  int idx = 0;
775  polys->indexBuffer()->resize( (z-1)*(x-1)*4 );
776  for(int i=0; i<z-1; ++i)
777  {
778  for(int j=0; j<x-1; ++j)
779  {
780  polys->indexBuffer()->at(idx++) = j+0 + x*(i+1);
781  polys->indexBuffer()->at(idx++) = j+1 + x*(i+1);
782  polys->indexBuffer()->at(idx++) = j+1 + x*(i+0);
783  polys->indexBuffer()->at(idx++) = j+0 + x*(i+0);
784  }
785  }
786 
787 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
788  geom->makeGLESFriendly();
789 #endif
790 
791  return geom;
792 }
793 //-----------------------------------------------------------------------------
794 ref<Geometry> vl::makePoints( const std::vector< vec3>& pos, const fvec4& color )
795 {
796  ref<Geometry> geom = new Geometry;
797  geom->setObjectName("Points");
798 
799  ref<ArrayFloat3> vert3 = new ArrayFloat3;
800  ref<ArrayFloat4> col4 = new ArrayFloat4;
801  geom->setVertexArray( vert3.get() );
802  geom->setColorArray( col4.get() );
803  vert3->resize( (int)pos.size() );
804  col4->resize( (int)pos.size() );
805 
806  for(unsigned i=0; i<pos.size(); ++i)
807  {
808  vert3->at(i) = (fvec3)pos[i];
809  col4->at(i) = color;
810  }
811 
812  geom->drawCalls().push_back( new DrawArrays(PT_POINTS, 0, (int)vert3->size() ));
813 
814 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
815  geom->makeGLESFriendly();
816 #endif
817 
818  return geom;
819 }
820 //-----------------------------------------------------------------------------
821 ref<Geometry> vl::makeIcosahedron( const vec3& origin, real diameter )
822 {
823  ref<Geometry> geom = new Geometry;
824  geom->setObjectName("Icosahedron");
825 
826  ref<ArrayFloat3> vert3 = new ArrayFloat3;
827  geom->setVertexArray(vert3.get());
828 
829  // red book 1.4 p89
830 
831  const real x = 0.525731112119133606f / 1.0f;
832  const real z = 0.850650808352039932f / 1.0f;
833  const real radius = diameter / 2.0f;
834 
835  vert3->resize( 12 );
836 
837  vert3->at(0) = (fvec3)(origin + vec3(-x, 0.0, +z)*radius);
838  vert3->at(1) = (fvec3)(origin + vec3(+x, 0.0, +z)*radius);
839  vert3->at(2) = (fvec3)(origin + vec3(-x, 0.0, -z)*radius);
840  vert3->at(3) = (fvec3)(origin + vec3(+x, 0.0, -z)*radius);
841 
842  vert3->at(4) = (fvec3)(origin + vec3(0.0, +z, +x)*radius);
843  vert3->at(5) = (fvec3)(origin + vec3(0.0, +z, -x)*radius);
844  vert3->at(6) = (fvec3)(origin + vec3(0.0, -z, +x)*radius);
845  vert3->at(7) = (fvec3)(origin + vec3(0.0, -z, -x)*radius);
846 
847  vert3->at(8) = (fvec3)(origin + vec3(+z, +x, 0.0)*radius);
848  vert3->at(9) = (fvec3)(origin + vec3(-z, +x, 0.0)*radius);
849  vert3->at(10) = (fvec3)(origin + vec3(+z, -x, 0.0)*radius);
850  vert3->at(11) = (fvec3)(origin + vec3(-z, -x, 0.0)*radius);
851 
852  unsigned short faces[20][3] =
853  {
854  {1,4,0}, {4,9,0}, {4,5,9}, {8,5,4}, {1,8,4},
855  {1,10,8}, {10,3,8}, {8,3,5}, {3,2,5}, {3,7,2},
856  {3,10,7}, {10,6,7}, {6,11,7}, {6,0,11}, {6,1,0},
857  {10,1,6}, {11,0,9}, {2,11,9}, {5,2,9}, {11,2,7}
858  };
859 
861  geom->drawCalls().push_back(polys.get());
862  polys->indexBuffer()->resize(20*3);
863  memcpy(polys->indexBuffer()->ptr(), faces, sizeof(faces));
864 
865 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
866  geom->makeGLESFriendly();
867 #endif
868 
869  return geom;
870 }
871 //-----------------------------------------------------------------------------
872 ref<Geometry> vl::makeCircle( vec3 origin, real radius, int slices )
873 {
874  ref< Geometry > geom = new Geometry;
875  geom->setObjectName("Circle");
876 
877  ref< ArrayFloat3 > points = new ArrayFloat3;
878  geom->setVertexArray(points.get());
879  points->resize( slices );
880  for(int i=0; i<slices; ++i)
881  {
882  real t = 360.0f * i / slices;
883  vec3 v = mat4::getRotation(t,0,1,0) * vec3(radius,0,0) + origin;
884  points->at(i) = (fvec3)v;
885  }
886  geom->drawCalls().push_back( new DrawArrays(PT_LINE_LOOP, 0, (int)points->size()) );
887 
888 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
889  geom->makeGLESFriendly();
890 #endif
891 
892  return geom;
893 }
894 //-----------------------------------------------------------------------------
895 ref<Geometry> vl::makeCapsule(float radius, float height, int segments, ECapsuleCap top_cap, ECapsuleCap bottom_cap, const fvec4& top_col, const fvec4& bottom_col)
896 {
897  float height2 = height / 2.0f;
898 
899  ref<Geometry> geom = new Geometry;
900  geom->setObjectName("Capsule");
901 
902  ref<ArrayFloat3> vert_array = new ArrayFloat3;
903  ref<ArrayFloat4> colr_array = new ArrayFloat4;
904  geom->setVertexArray(vert_array.get());
905  geom->setColorArray (colr_array.get());
906  std::vector<fvec3> verts;
907  std::vector<fvec4> cols;
908 
909  // upper
910  for(int i=0; i<segments; ++i)
911  {
912  float a = (float)i/segments*fPi*2.0f;
913  fvec3 v(::cos(a)*radius,+height2,::sin(a)*radius);
914  verts.push_back(v);
915  cols.push_back(top_col);
916  }
917  if (top_col != bottom_col)
918  {
919  // mid-upper
920  for(int i=0; i<segments; ++i)
921  {
922  float a = (float)i/segments*fPi*2.0f;
923  fvec3 v(::cos(a)*radius,0,::sin(a)*radius);
924  verts.push_back(v);
925  cols.push_back(top_col);
926  }
927  // mid-lower
928  for(int i=0; i<segments; ++i)
929  {
930  float a = (float)i/segments*fPi*2.0f;
931  fvec3 v(::cos(a)*radius,0,::sin(a)*radius);
932  verts.push_back(v);
933  cols.push_back(bottom_col);
934  }
937  geom->drawCalls().push_back(de_up.get());
938  geom->drawCalls().push_back(de_lo.get());
939  de_up->indexBuffer()->resize(segments*4);
940  de_lo->indexBuffer()->resize(segments*4);
941  int upup = segments*0;
942  int uplo = segments*1;
943  int loup = segments*2;
944  int lolo = segments*3;
945  for(int i=0; i<segments; ++i)
946  {
947  int i1 = (i+1) % segments;
948  de_up->indexBuffer()->at(i*4+3) = uplo + i;
949  de_up->indexBuffer()->at(i*4+2) = uplo + i1;
950  de_up->indexBuffer()->at(i*4+1) = upup + i1;
951  de_up->indexBuffer()->at(i*4+0) = upup + i;
952 
953  de_lo->indexBuffer()->at(i*4+3) = lolo + i;
954  de_lo->indexBuffer()->at(i*4+2) = lolo + i1;
955  de_lo->indexBuffer()->at(i*4+1) = loup + i1;
956  de_lo->indexBuffer()->at(i*4+0) = loup + i;
957  }
958  }
959  else
960  {
962  geom->drawCalls().push_back(de_up.get());
963  de_up->indexBuffer()->resize(segments*4);
964  int upup = segments*0;
965  int uplo = segments*1;
966  for(int i=0; i<segments; ++i)
967  {
968  int i1 = (i+1) % segments;
969  de_up->indexBuffer()->at(i*4+3) = uplo + i;
970  de_up->indexBuffer()->at(i*4+2) = uplo + i1;
971  de_up->indexBuffer()->at(i*4+1) = upup + i1;
972  de_up->indexBuffer()->at(i*4+0) = upup + i;
973  }
974  }
975  // lower
976  for(int i=0; i<segments; ++i)
977  {
978  float a = (float)i/segments*fPi*2.0f;
979  fvec3 v(::cos(a)*radius,-height2,::sin(a)*radius);
980  verts.push_back(v);
981  cols.push_back(bottom_col);
982  }
983  // caps
984  if (top_cap == CC_FlatCap)
985  {
986  int start = (int)verts.size();
987  for(int i=0; i<segments; ++i)
988  {
989  float a = (float)i/segments*fPi*2.0f;
990  fvec3 v(::cos(a)*radius,+height2,::sin(a)*radius);
991  verts.push_back(v);
992  cols.push_back(top_col);
993  }
995  geom->drawCalls().push_back(de.get());
996  de->indexBuffer()->resize(segments);
997  for(int i=0,j=segments; j--; ++i)
998  de->indexBuffer()->at(j) = start + i;
999  }
1000  if (bottom_cap == CC_FlatCap)
1001  {
1002  int start = (int)verts.size();
1003  for(int i=0; i<segments; ++i)
1004  {
1005  float a = (float)i/segments*fPi*2.0f;
1006  fvec3 v(::cos(a)*radius,-height2,::sin(a)*radius);
1007  verts.push_back(v);
1008  cols.push_back(bottom_col);
1009  }
1011  geom->drawCalls().push_back(de.get());
1012  de->indexBuffer()->resize(segments);
1013  for(int i=0; i<segments; ++i)
1014  de->indexBuffer()->at(i) = start + i;
1015  }
1016  int segments2 = segments/3; if (segments2<2) segments2=2;
1017  if (top_cap == CC_RoundedCap)
1018  {
1019  int start = (int)verts.size();
1020  for(int j=0; j<segments2; ++j)
1021  {
1022  float aj = (float)j/segments2*fPi/2.0f;
1023  for(int i=0; i<segments; ++i)
1024  {
1025  float a = (float)i/segments*360;
1026  fvec3 v(::cos(aj)*radius,::sin(aj)*radius,0);
1027  verts.push_back(fmat4::getRotation(a,0,1,0) * v + fvec3(0,height2,0));
1028  cols.push_back(top_col);
1029  }
1030  }
1031  // top point
1032  verts.push_back(fvec3(0,+height2+radius,0));
1033  cols.push_back(top_col);
1034 
1036  geom->drawCalls().push_back(de_quads.get());
1037  de_quads->indexBuffer()->resize(segments*(segments2-1)*4);
1038  for(int j=0,idx=0; j<segments2-1; ++j)
1039  {
1040  int uplo = start+segments*j;
1041  int upup = start+segments*(j+1);
1042  for(int i=0; i<segments; ++i)
1043  {
1044  int i1 = (i+1) % segments;
1045  de_quads->indexBuffer()->at(idx++) = uplo + i;
1046  de_quads->indexBuffer()->at(idx++) = uplo + i1;
1047  de_quads->indexBuffer()->at(idx++) = upup + i1;
1048  de_quads->indexBuffer()->at(idx++) = upup + i;
1049  }
1050  }
1051 
1053  geom->drawCalls().push_back(de.get());
1054  de->indexBuffer()->resize(segments+2);
1055  de->indexBuffer()->at(0) = (GLuint)verts.size()-1;
1056  for(int i=0; i<segments+1; ++i)
1057  de->indexBuffer()->at(i+1) = (GLuint)verts.size()-1-segments+i%segments;
1058  }
1059  if (bottom_cap == CC_RoundedCap)
1060  {
1061  int start = (int)verts.size();
1062  for(int j=0; j<segments2; ++j)
1063  {
1064  float aj = (float)j/segments2*fPi/2.0f;
1065  for(int i=0; i<segments; ++i)
1066  {
1067  float a = -(float)i/segments*360;
1068  fvec3 v(::cos(aj)*radius,-::sin(aj)*radius,0);
1069  verts.push_back(fmat4::getRotation(a,0,1,0) * v + fvec3(0,-height2,0));
1070  cols.push_back(bottom_col);
1071  }
1072  }
1073  // bottom point
1074  verts.push_back(fvec3(0,-height2-radius,0));
1075  cols.push_back(bottom_col);
1076 
1078  geom->drawCalls().push_back(de_quads.get());
1079  de_quads->indexBuffer()->resize(segments*(segments2-1)*4);
1080  for(int j=0,idx=0; j<segments2-1; ++j)
1081  {
1082  int uplo = start+segments*j;
1083  int upup = start+segments*(j+1);
1084  for(int i=0; i<segments; ++i)
1085  {
1086  int i1 = (i+1) % segments;
1087  de_quads->indexBuffer()->at(idx++) = uplo + i;
1088  de_quads->indexBuffer()->at(idx++) = uplo + i1;
1089  de_quads->indexBuffer()->at(idx++) = upup + i1;
1090  de_quads->indexBuffer()->at(idx++) = upup + i;
1091  }
1092  }
1093 
1095  geom->drawCalls().push_back(de.get());
1096  de->indexBuffer()->resize(segments+2);
1097  de->indexBuffer()->at(0) = (GLuint)verts.size()-1;
1098  for(int i=0; i<segments+1; ++i)
1099  de->indexBuffer()->at(i+1) = (GLuint)verts.size()-1-segments+i%segments;
1100  }
1101 
1102  vert_array->initFrom(verts);
1103  colr_array->initFrom(cols);
1104 
1105 #if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2)
1106  geom->makeGLESFriendly();
1107 #endif
1108 
1109  return geom;
1110 }
1111 //-----------------------------------------------------------------------------
See DrawElements.
const T_Scalar & t() const
Definition: Vector2.hpp:145
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
An array of vl::fvec4.
Definition: Array.hpp:416
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
const T * get() const
Definition: Object.hpp:128
VLGRAPHICS_EXPORT ref< Geometry > makeCylinder(const vec3 &origin, real diameter=1, real height=1, int phi=20, int theta=2, bool top=true, bool bottom=true)
Creates a cylinder.
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
T sin(T a)
Definition: glsl_math.hpp:199
const T_Scalar & s() const
Definition: Vector2.hpp:144
const T_Scalar & z() const
Definition: Vector3.hpp:91
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
VLGRAPHICS_EXPORT ref< Geometry > makeCone(const vec3 &origin, real diameter=1, real height=1, int phi=20, bool bottom=true)
Creates a cone.
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
VLGRAPHICS_EXPORT ref< Geometry > makeTeapot(const vec3 &origin, real diameter=1, int detail=8)
Creates a classic Newell&#39;s teapot.
Removes from a Geometry the vertices with the same attributes.
vec3 center() const
Returns the center of the AABB.
Definition: AABB.cpp:184
void removeDoubles(Geometry *geom)
void resize(size_t dim)
Definition: Array.hpp:233
void setNormalArray(ArrayAbstract *data)
Conventional normal array.
Definition: Geometry.cpp:164
void setColorArray(const fvec4 &color)
Fills the color array with the given color.
Definition: Geometry.hpp:108
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
Points & points()
The control points grid defining the bicubic Bézier patch(es).
Visualization Library main namespace.
const float fPi
Greek Pi constant using float precision.
Definition: std_types.hpp:71
const unsigned char * ptr() const
Returns the pointer to the first element of the local buffer. Equivalent to bufferObject()->ptr() ...
Definition: Array.hpp:103
Vector2< float > fvec2
A 2 components vector with float precision.
Definition: Vector2.hpp:282
VLGRAPHICS_EXPORT ref< Geometry > makeBox(const vec3 &origin, real xside=1, real yside=1, real zside=1, bool tex_coords=true)
Creates a box.
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
VLGRAPHICS_EXPORT ref< Geometry > makeIcosahedron(const vec3 &origin, real diameter)
Creates an icosahedron.
real width() const
Returns the width of the AABB computed as max.x - min.x.
Definition: AABB.cpp:151
Defines one or more concatenated bicubic Bézier patches to be used with the BezierSurface class...
void initFrom(const std::vector< T_VectorType > &vector)
Definition: Array.hpp:395
const vec3 & maxCorner() const
Returns the corner of the AABB with the maximum x y z coordinates.
Definition: AABB.hpp:193
float max(float a, float b)
Definition: Vector2.hpp:311
See DrawElements.
The BezierSurface class implements a Geometry that is capable of visualizing multiple bicubic Bézier ...
float min(float a, float b)
Definition: Vector2.hpp:307
VLGRAPHICS_EXPORT ref< Geometry > makeTorus(const vec3 &origin, real diameter=1, real thickness=0.2, int phi=10, int theta=10, float tex_coords=0.0f)
Creates torus. This function generates also appropriate normals.
void setDetail(unsigned i)
The sampling level of the patch, must not be less than 2. The higher the sampling level...
std::vector< ref< BezierPatch > > & patches()
Returns the Bézier patches that are part of this Bézier surface.
VLGRAPHICS_EXPORT ref< Geometry > makeCapsule(float radius, float height, int segments, ECapsuleCap top_cap, ECapsuleCap bottom_cap, const fvec4 &top_col, const fvec4 &bottom_col)
Creates a 3d capsule with rounded, flat or no caps.
const T_Scalar & y() const
Definition: Vector3.hpp:90
VLGRAPHICS_EXPORT ref< Geometry > makePyramid(const vec3 &origin, real side=1, real height=1)
Creates a pyramid.
void setTexCoordArray(int tex_unit, ArrayAbstract *data)
Conventional texture coords arrays.
Definition: Geometry.cpp:222
void transform(const mat4 &matr, bool normalize=true)
Transforms vertices and normals belonging to this geometry.
Definition: Geometry.cpp:399
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
void updateBezierSurface(bool gen_tex_coords=true)
Generates the Bézier surface geometry based on the current patches and detail.
const vec3 & minCorner() const
Returns the corner of the AABB with the minimum x y z coordinates.
Definition: AABB.hpp:190
static Matrix4 & getRotation(Matrix4 &out, float degrees, float x, float y, float z)
Definition: Matrix4.hpp:904
T_VectorType & at(size_t i)
Definition: Array.hpp:255
fvec3 vec3
Defined as: &#39;typedef fvec3 vec3&#39;. See also VL_PIPELINE_PRECISION.
Definition: Vector3.hpp:269
VLGRAPHICS_EXPORT ref< Geometry > makeIcosphere(const vec3 &pos, real diameter=1, int detail=2, bool remove_doubles=true)
Creates a sphere by iteratively subdividing an icosahedron.
virtual size_t size() const =0
Returns the number of elements of an array.
VLGRAPHICS_EXPORT ref< Geometry > makePoints(const std::vector< vec3 > &pos, const fvec4 &color=white)
Creates a set of points.
static Matrix4 & getTranslation(Matrix4 &out, const Vector3< float > &v)
Definition: Matrix4.hpp:548
T cos(T a)
Definition: glsl_math.hpp:225
static Matrix4 & getScaling(Matrix4 &out, const Vector3< float > &v)
Definition: Matrix4.hpp:584
const T_Scalar & x() const
Definition: Vector3.hpp:89
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
An array of vl::fvec3.
Definition: Array.hpp:414
const AABB & boundingBox() const
Returns the bounding box of a Renderable without recomputing the bounds if dirty. ...
Definition: Renderable.hpp:151
VLGRAPHICS_EXPORT ref< Geometry > makeGrid(const vec3 &origin, real xside, real zside, int x, int z, bool gen_texcoords=false, fvec2 uv0=fvec2(0, 0), fvec2 uv1=fvec2(1, 1), bool center=true)
Creates a 2D grid.
VLGRAPHICS_EXPORT ref< Geometry > makeUVSphere(const vec3 &origin, real diameter=1, int phi=20, int theta=20)
Creates a uv sphere.
void makeGLESFriendly()
Calls triangulateDrawCalls() and shrinkDrawCalls().
Definition: Geometry.cpp:1014
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
An array of vl::fvec2.
Definition: Array.hpp:412
#define VL_CHECK(expr)
Definition: checks.hpp:73
VLGRAPHICS_EXPORT ref< Geometry > makeCircle(vec3 origin, real radius, int slices=60)
Creates a 2D circle.
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102