Created
July 13, 2011 12:22
-
-
Save roxlu/1080202 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//! \p detail can be between 0 ( = icosahedron) and 8 (extremely detailed sphere) | |
//! a value of 2 yelds already very good results. | |
ref<Geometry> vl::makeIcosphere(const vec3& pos, Real diameter, int detail, bool remove_doubles) | |
{ | |
ref<Geometry> geom = new Geometry; | |
geom->setObjectName("Icosphere"); | |
ref<ArrayFloat3> coords = new ArrayFloat3; | |
ref<ArrayFloat3> norms = new ArrayFloat3; | |
ref<DrawElementsUInt> polys = new DrawElementsUInt(PT_TRIANGLES); | |
const Real X = (Real)0.525731112119133606; | |
const Real Z = (Real)0.850650808352039932; | |
std::vector< vec3 > verts; | |
verts.push_back( vec3(-X, 0, Z) ); | |
verts.push_back( vec3(X, 0, Z) ); | |
verts.push_back( vec3(-X, 0, -Z) ); | |
verts.push_back( vec3(X, 0, -Z) ); | |
verts.push_back( vec3(0, Z, X) ); | |
verts.push_back( vec3(0, Z, -X) ); | |
verts.push_back( vec3(0, -Z, X) ); | |
verts.push_back( vec3(0, -Z, -X) ); | |
verts.push_back( vec3(Z, X, 0) ); | |
verts.push_back( vec3(-Z, X, 0) ); | |
verts.push_back( vec3(Z, -X, 0) ); | |
verts.push_back( vec3(-Z, -X, 0) ); | |
int idxs[] = { | |
1,4,0, 4,9,0, 4,5,9, 8,5,4, 1,8,4, | |
1,10,8, 10,3,8, 8,3,5, 3,2,5, 3,7,2, | |
3,10,7, 10,6,7, 6,11,7, 6,0,11, 6,1,0, | |
10,1,6, 11,0,9, 2,11,9, 5,2,9, 11,2,7 | |
}; | |
std::vector<int> indices; | |
for(int i=0; i<4*5*3; ++i) | |
indices.push_back(idxs[i]); | |
// triangulate the icosahedron | |
if (detail>8) | |
detail = 8; | |
if (detail<0) | |
detail = 0; | |
for(int i=0; i<detail; ++i) | |
{ | |
std::vector<int> indices2; | |
std::vector< vec3 > verts2; | |
for( int j=0, idx=0; j<(int)indices.size(); j+=3) | |
{ | |
indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); | |
indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); | |
indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); | |
indices2.push_back(idx++); indices2.push_back(idx++); indices2.push_back(idx++); | |
vec3 v1 = verts[ indices[j+0] ]; v1.normalize(); | |
vec3 v2 = verts[ indices[j+1] ]; v2.normalize(); | |
vec3 v3 = verts[ indices[j+2] ]; v3.normalize(); | |
vec3 a = (v1 + v2) * 0.5f; a.normalize(); | |
vec3 b = (v2 + v3) * 0.5f; b.normalize(); | |
vec3 c = (v3 + v1) * 0.5f; c.normalize(); | |
verts2.push_back(v1); verts2.push_back( a); verts2.push_back(c); | |
verts2.push_back( a); verts2.push_back(v2); verts2.push_back(b); | |
verts2.push_back( a); verts2.push_back( b); verts2.push_back(c); | |
verts2.push_back( c); verts2.push_back( b); verts2.push_back(v3); | |
} | |
verts = verts2; | |
indices = indices2; | |
} | |
// generate sphere vertices and connection information | |
Real radius = diameter / 2; | |
coords->resize( (int)verts.size() ); | |
norms->resize( (int)verts.size() ); | |
for( int i=0; i<(int)verts.size(); ++i ) | |
{ | |
coords->at(i) = (fvec3)(verts[i]*radius + pos); | |
vec3 n = verts[i]; | |
n.normalize(); | |
norms->at(i) = (fvec3)n; | |
} | |
polys->indices()->resize( (int)indices.size() ); | |
for(int i=0; i<(int)indices.size(); ++i) | |
{ | |
VL_CHECK( indices[i] < (int)coords->size() ) | |
polys->indices()->at(i) = indices[i]; | |
} | |
geom->setVertexArray(coords.get()); | |
geom->setNormalArray(norms.get()); | |
geom->drawCalls()->push_back(polys.get()); | |
if (remove_doubles) | |
{ | |
DoubleVertexRemover dvr; | |
dvr.removeDoubles(geom.get()); | |
} | |
#if defined(VL_OPENGL_ES1) || defined(VL_OPENGL_ES2) | |
geom->makeGLESFriendly(); | |
#endif | |
return geom; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment