1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library
2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra.
3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//
6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla
7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed
8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "icosphere.h"
11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <GL/gl.h>
13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include <map>
14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathusing namespace Eigen;
16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//--------------------------------------------------------------------------------
18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// icosahedron data
19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//--------------------------------------------------------------------------------
20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define X .525731112119133606
21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define Z .850650808352039932
22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstatic GLfloat vdata[12][3] = {
24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {-X, 0.0, Z}, {X, 0.0, Z}, {-X, 0.0, -Z}, {X, 0.0, -Z},
25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {0.0, Z, X}, {0.0, Z, -X}, {0.0, -Z, X}, {0.0, -Z, -X},
26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {Z, X, 0.0}, {-Z, X, 0.0}, {Z, -X, 0.0}, {-Z, -X, 0.0}
27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath};
28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstatic GLint tindices[20][3] = {
30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {0,4,1}, {0,9,4}, {9,5,4}, {4,5,8}, {4,8,1},
31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {8,10,1}, {8,3,10}, {5,3,8}, {5,2,3}, {2,7,3},
32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {7,10,3}, {7,6,10}, {7,11,6}, {11,0,6}, {0,1,6},
33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath   {6,1,10}, {9,0,11}, {9,11,2}, {9,2,5}, {7,2,11} };
34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath//--------------------------------------------------------------------------------
35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathIcoSphere::IcoSphere(unsigned int levels)
37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  // init with an icosahedron
39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for (int i = 0; i < 12; i++)
40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mVertices.push_back(Map<Vector3f>(vdata[i]));
41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mIndices.push_back(new std::vector<int>);
42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  std::vector<int>& indices = *mIndices.back();
43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for (int i = 0; i < 20; i++)
44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int k = 0; k < 3; k++)
46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      indices.push_back(tindices[i][k]);
47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mListIds.push_back(0);
49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  while(mIndices.size()<levels)
51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    _subdivide();
52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathconst std::vector<int>& IcoSphere::indices(int level) const
55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  while (level>=int(mIndices.size()))
57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const_cast<IcoSphere*>(this)->_subdivide();
58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  return *mIndices[level];
59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid IcoSphere::_subdivide(void)
62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  typedef unsigned long long Key;
64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  std::map<Key,int> edgeMap;
65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  const std::vector<int>& indices = *mIndices.back();
66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mIndices.push_back(new std::vector<int>);
67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  std::vector<int>& refinedIndices = *mIndices.back();
68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  int end = indices.size();
69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  for (int i=0; i<end; i+=3)
70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    int ids0[3],  // indices of outer vertices
72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ids1[3];  // indices of edge vertices
73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    for (int k=0; k<3; ++k)
74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    {
75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      int k1 = (k+1)%3;
76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      int e0 = indices[i+k];
77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      int e1 = indices[i+k1];
78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      ids0[k] = e0;
79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (e1>e0)
80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        std::swap(e0,e1);
81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      Key edgeKey = Key(e0) | (Key(e1)<<32);
82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      std::map<Key,int>::iterator it = edgeMap.find(edgeKey);
83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      if (it==edgeMap.end())
84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      {
85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ids1[k] = mVertices.size();
86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        edgeMap[edgeKey] = ids1[k];
87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        mVertices.push_back( (mVertices[e0]+mVertices[e1]).normalized() );
88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      }
89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      else
90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath        ids1[k] = it->second;
91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    }
92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refinedIndices.push_back(ids0[0]); refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[2]);
93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refinedIndices.push_back(ids0[1]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[0]);
94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refinedIndices.push_back(ids0[2]); refinedIndices.push_back(ids1[2]); refinedIndices.push_back(ids1[1]);
95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[2]);
96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  mListIds.push_back(0);
98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid IcoSphere::draw(int level)
101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{
102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  while (level>=int(mIndices.size()))
103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    const_cast<IcoSphere*>(this)->_subdivide();
104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  if (mListIds[level]==0)
105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  {
106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    mListIds[level] = glGenLists(1);
107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    glNewList(mListIds[level], GL_COMPILE);
108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glNormalPointer(GL_FLOAT, 0, mVertices[0].data());
110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glEnableClientState(GL_VERTEX_ARRAY);
111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glEnableClientState(GL_NORMAL_ARRAY);
112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glDrawElements(GL_TRIANGLES, mIndices[level]->size(), GL_UNSIGNED_INT, &(mIndices[level]->at(0)));
113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glDisableClientState(GL_VERTEX_ARRAY);
114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath      glDisableClientState(GL_NORMAL_ARRAY);
115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath    glEndList();
116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  }
117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath  glCallList(mListIds[level]);
118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath}
119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath
121