to complete : an icosphere :
this code adapted for irrlicht come from : http://www.ogre3d.org/tikiwiki/Ogre+Pro ... ry+Library (MIT licence)
Code: Select all
//-----------------------------------------------------------------------------------------------------------------
// make IcoSphere
//-----------------------------------------------------------------------------------------------------------------
scene::IMesh* createIcoSphere(f32 mRadius, s32 mNumIterations) const
{
std::vector<core::vector3df> vertices;
int offset = 0;
/// Step 1 : Generate icosahedron
f32 phi = .5f*(1.f+sqrt(5.f));
f32 invnorm = 1/sqrt(phi*phi+1);
vertices.push_back(invnorm*core::vector3df(-1, phi, 0)); //0
vertices.push_back(invnorm*core::vector3df( 1, phi, 0)); //1
vertices.push_back(invnorm*core::vector3df(0, 1, -phi)); //2
vertices.push_back(invnorm*core::vector3df(0, 1, phi)); //3
vertices.push_back(invnorm*core::vector3df(-phi,0, -1)); //4
vertices.push_back(invnorm*core::vector3df(-phi,0, 1)); //5
vertices.push_back(invnorm*core::vector3df( phi,0, -1)); //6
vertices.push_back(invnorm*core::vector3df( phi,0, 1)); //7
vertices.push_back(invnorm*core::vector3df(0, -1, -phi)); //8
vertices.push_back(invnorm*core::vector3df(0, -1, phi)); //9
vertices.push_back(invnorm*core::vector3df(-1, -phi,0)); //10
vertices.push_back(invnorm*core::vector3df( 1, -phi,0)); //11
int firstFaces[] = {0,1,2,
0,3,1,
0,4,5,
1,7,6,
1,6,2,
1,3,7,
0,2,4,
0,5,3,
2,6,8,
2,8,4,
3,5,9,
3,9,7,
11,6,7,
10,5,4,
10,4,8,
10,9,5,
11,8,6,
11,7,9,
10,8,11,
10,11,9
};
std::vector<int> faces(firstFaces, firstFaces + sizeof(firstFaces)/sizeof(*firstFaces));
int size = 60;
/// Step 2 : tessellate
for (unsigned short iteration = 0; iteration<mNumIterations; iteration++)
{
size*=4;
std::vector<int> newFaces;
newFaces.clear();
//newFaces.resize(size);
for (int i=0; i<size/12; i++)
{
int i1 = faces[i*3];
int i2 = faces[i*3+1];
int i3 = faces[i*3+2];
int i12 = vertices.size();
int i23 = i12+1;
int i13 = i12+2;
core::vector3df v1 = vertices[i1];
core::vector3df v2 = vertices[i2];
core::vector3df v3 = vertices[i3];
//make 1 vertice at the center of each edge and project it onto the sphere
vertices.push_back((v1+v2).normalize());
vertices.push_back((v2+v3).normalize());
vertices.push_back((v1+v3).normalize());
//now recreate indices
newFaces.push_back(i1);
newFaces.push_back(i12);
newFaces.push_back(i13);
newFaces.push_back(i2);
newFaces.push_back(i23);
newFaces.push_back(i12);
newFaces.push_back(i3);
newFaces.push_back(i13);
newFaces.push_back(i23);
newFaces.push_back(i12);
newFaces.push_back(i23);
newFaces.push_back(i13);
}
faces.swap(newFaces);
}
/// Step 3 : generate texcoords
std::vector<core::vector2df> texCoords;
for (unsigned short i=0;i<vertices.size();i++)
{
const core::vector3df& vec = vertices[i];
f32 u, v;
f32 r0 = sqrtf(vec.X*vec.X+vec.Z*vec.Z);
f32 alpha;
alpha = atan2f(vec.Z,vec.X);
u = alpha/core::PI+.5f;
v = atan2f(vec.Y, r0)/core::PI + .5f;
texCoords.push_back(core::vector2df(u,v));
}
/// Step 4 : fix texcoords
// find vertices to split
std::vector<int> indexToSplit;
for (unsigned int i=0;i<faces.size()/3;i++)
{
core::vector2df& t0 = texCoords[faces[i*3+0]];
core::vector2df& t1 = texCoords[faces[i*3+1]];
core::vector2df& t2 = texCoords[faces[i*3+2]];
if (abs(t2.X-t0.X)>0.5)
{
if (t0.X<0.5)
indexToSplit.push_back(faces[i*3]);
else
indexToSplit.push_back(faces[i*3+2]);
}
if (abs(t1.X-t0.X)>0.5)
{
if (t0.X<0.5)
indexToSplit.push_back(faces[i*3]);
else
indexToSplit.push_back(faces[i*3+1]);
}
if (abs(t2.X-t1.X)>0.5)
{
if (t1.X<0.5)
indexToSplit.push_back(faces[i*3+1]);
else
indexToSplit.push_back(faces[i*3+2]);
}
}
//split vertices
for (unsigned short i=0;i<indexToSplit.size();i++)
{
int index = indexToSplit[i];
//duplicate vertex
core::vector3df v = vertices[index];
core::vector2df t = texCoords[index] + core::vector2df(1,0);
vertices.push_back(v);
texCoords.push_back(t);
int newIndex = vertices.size()-1;
//reassign indices
for (unsigned short j=0;j<faces.size();j++)
{
if (faces[j]==index)
{
int index1 = faces[(j+1)%3+(j/3)*3];
int index2 = faces[(j+2)%3+(j/3)*3];
if ((texCoords[index1].X>0.5) || (texCoords[index2].X>0.5))
{
faces[j] = newIndex;
}
}
}
}
/// Step 5 : realize
SMeshBuffer* buffer = new SMeshBuffer();
video::S3DVertex vtx;
vtx.Color.set(255,255,255,255);
for (unsigned short i=0; i<vertices.size(); i++)
{
vtx.Pos.set( mRadius*vertices[i] );
vtx.Normal.set( vertices[i] );
vtx.TCoords.set( texCoords[i].X, texCoords[i].X);
buffer->Vertices.push_back(vtx);
}
for (unsigned short i=0; i<size; i++)
{
buffer->Indices.push_back(offset+faces[i]);
}
offset+=vertices.size();
buffer->Material.BackfaceCulling = true;
buffer->Material.Wireframe = true;
buffer->recalculateBoundingBox();
buffer->setHardwareMappingHint(EHM_STATIC);
SMesh* mesh = new SMesh();
mesh->addMeshBuffer(buffer);
mesh->recalculateBoundingBox();
buffer->drop();
return mesh;
}