00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
00455 thickness /= 2.0f;
00456 const real radius = diameter / 2.0f - thickness;
00457
00458
00459 ref<ArrayFloat3> vert3 = new ArrayFloat3;
00460 geom->setVertexArray(vert3.get());
00461 vert3->resize( (phi+1) * (theta+1) );
00462
00463
00464 ref<ArrayFloat3> norm3 = new ArrayFloat3;
00465 geom->setNormalArray(norm3.get());
00466 norm3->resize( (phi+1) * (theta+1) );
00467
00468
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
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
00536
00537
00538
00539
00540
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
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
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
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
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);
00763 float tv = (float)i/(z-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
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
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
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
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
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
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
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
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
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