diff options
author | Gael Guennebaud <g.gael@free.fr> | 2008-09-11 11:19:34 +0000 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2008-09-11 11:19:34 +0000 |
commit | e5c50afed6f0d7af099ea4a87a160451a706a186 (patch) | |
tree | 8b7319c1ae77f05c4dd832c87c7853d72bc1dddd /demos/opengl | |
parent | 5e9ee8863e0ffe38551dcffb195a894129019a71 (diff) |
* Quaternion: added dot product and angularDistance functions. The latter is
based on the former.
* opengl_demo: makes IcoSphere better (vertices are instanciated only once) and
removed the generation of a big geometry for the fancy spheres...
Diffstat (limited to 'demos/opengl')
-rw-r--r-- | demos/opengl/icosphere.cpp | 40 | ||||
-rw-r--r-- | demos/opengl/quaternion_demo.cpp | 194 |
2 files changed, 123 insertions, 111 deletions
diff --git a/demos/opengl/icosphere.cpp b/demos/opengl/icosphere.cpp index 5f7823124..042ad6076 100644 --- a/demos/opengl/icosphere.cpp +++ b/demos/opengl/icosphere.cpp @@ -25,6 +25,7 @@ #include "icosphere.h" #include <GL/gl.h> +#include <map> using namespace Eigen; @@ -74,24 +75,39 @@ const std::vector<int>& IcoSphere::indices(int level) const void IcoSphere::_subdivide(void) { + typedef unsigned long long Key; + std::map<Key,int> edgeMap; const std::vector<int>& indices = *mIndices.back(); mIndices.push_back(new std::vector<int>); std::vector<int>& refinedIndices = *mIndices.back(); int end = indices.size(); for (int i=0; i<end; i+=3) { - int i0, i1, i2; - Vector3f v0 = mVertices[i0=indices[i+0]]; - Vector3f v1 = mVertices[i1=indices[i+1]]; - Vector3f v2 = mVertices[i2=indices[i+2]]; - int start = mVertices.size(); - mVertices.push_back( (v0+v1).normalized() ); - mVertices.push_back( (v1+v2).normalized() ); - mVertices.push_back( (v2+v0).normalized() ); - refinedIndices.push_back(i0); refinedIndices.push_back(start+0); refinedIndices.push_back(start+2); - refinedIndices.push_back(i1); refinedIndices.push_back(start+1); refinedIndices.push_back(start+0); - refinedIndices.push_back(i2); refinedIndices.push_back(start+2); refinedIndices.push_back(start+1); - refinedIndices.push_back(start+0); refinedIndices.push_back(start+1); refinedIndices.push_back(start+2); + int ids0[3], // indices of outer vertices + ids1[3]; // indices of edge vertices + for (int k=0; k<3; ++k) + { + int k1 = (k+1)%3; + int e0 = indices[i+k]; + int e1 = indices[i+k1]; + ids0[k] = e0; + if (e1>e0) + std::swap(e0,e1); + Key edgeKey = Key(e0) | (Key(e1)<<32); + std::map<Key,int>::iterator it = edgeMap.find(edgeKey); + if (it==edgeMap.end()) + { + ids1[k] = mVertices.size(); + edgeMap[edgeKey] = ids1[k]; + mVertices.push_back( (mVertices[e0]+mVertices[e1]).normalized() ); + } + else + ids1[k] = it->second; + } + refinedIndices.push_back(ids0[0]); refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[2]); + refinedIndices.push_back(ids0[1]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[0]); + refinedIndices.push_back(ids0[2]); refinedIndices.push_back(ids1[2]); refinedIndices.push_back(ids1[1]); + refinedIndices.push_back(ids1[0]); refinedIndices.push_back(ids1[1]); refinedIndices.push_back(ids1[2]); } mListIds.push_back(0); } diff --git a/demos/opengl/quaternion_demo.cpp b/demos/opengl/quaternion_demo.cpp index dbfc16c6b..31aeb4d73 100644 --- a/demos/opengl/quaternion_demo.cpp +++ b/demos/opengl/quaternion_demo.cpp @@ -41,6 +41,89 @@ using namespace Eigen; +class FancySpheres +{ + public: + FancySpheres() + { + const int levels = 4; + const float scale = 0.33; + float radius = 100; + std::vector<int> parents; + + // leval 0 + mCenters.push_back(Vector3f::Zero()); + parents.push_back(-1); + mRadii.push_back(radius); + + // generate level 1 using icosphere vertices + radius *= 0.45; + { + float dist = mRadii[0]*0.9; + for (int i=0; i<12; ++i) + { + mCenters.push_back(mIcoSphere.vertices()[i] * dist); + mRadii.push_back(radius); + parents.push_back(0); + } + } + + static const float angles [10] = { + 0, 0, + M_PI, 0.*M_PI, + M_PI, 0.5*M_PI, + M_PI, 1.*M_PI, + M_PI, 1.5*M_PI + }; + + // generate other levels + int start = 1; + for (int l=1; l<levels; l++) + { + radius *= scale; + int end = mCenters.size(); + for (int i=start; i<end; ++i) + { + Vector3f c = mCenters[i]; + Vector3f ax0 = (c - mCenters[parents[i]]).normalized(); + Vector3f ax1 = ax0.unitOrthogonal(); + Quaternionf q; + q.setFromTwoVectors(Vector3f::UnitZ(), ax0); + Transform3f t = Translation3f(c) * q * Scaling3f(mRadii[i]+radius); + for (int j=0; j<5; ++j) + { + Vector3f newC = c + ( (AngleAxisf(angles[j*2+1], ax0) + * AngleAxisf(angles[j*2+0] * (l==1 ? 0.35 : 0.5), ax1)) * ax0) + * (mRadii[i] + radius*0.8); + mCenters.push_back(newC); + mRadii.push_back(radius); + parents.push_back(i); + } + } + start = end; + } + } + + void draw() + { + int end = mCenters.size(); + glEnable(GL_NORMALIZE); + for (int i=0; i<end; ++i) + { + Transform3f t = Translation3f(mCenters[i]) * Scaling3f(mRadii[i]); + gpu.pushMatrix(GL_MODELVIEW); + gpu.multMatrix(t.matrix(),GL_MODELVIEW); + mIcoSphere.draw(2); + gpu.popMatrix(GL_MODELVIEW); + } + glDisable(GL_NORMALIZE); + } + protected: + std::vector<Vector3f> mCenters; + std::vector<float> mRadii; + IcoSphere mIcoSphere; +}; + // generic linear interpolation method template<typename T> T lerp(float t, const T& a, const T& b) @@ -156,7 +239,8 @@ void RenderingWidget::grabFrame(void) void RenderingWidget::drawScene() { - float length = 50; + static FancySpheres sFancySpheres; + float length = 200; gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitX(), Color(1,0,0,1)); gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitY(), Color(0,1,0,1)); gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitZ(), Color(0,0,1,1)); @@ -183,13 +267,14 @@ void RenderingWidget::drawScene() glEnable(GL_LIGHT1); glColor3f(0.4, 0.7, 0.4); - glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data()); - glNormalPointer(GL_FLOAT, 0, mNormals[0].data()); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glDrawArrays(GL_TRIANGLES, 0, mVertices.size()); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + sFancySpheres.draw(); +// glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data()); +// glNormalPointer(GL_FLOAT, 0, mNormals[0].data()); +// glEnableClientState(GL_VERTEX_ARRAY); +// glEnableClientState(GL_NORMAL_ARRAY); +// glDrawArrays(GL_TRIANGLES, 0, mVertices.size()); +// glDisableClientState(GL_VERTEX_ARRAY); +// glDisableClientState(GL_NORMAL_ARRAY); glDisable(GL_LIGHTING); } @@ -413,93 +498,6 @@ void RenderingWidget::initializeGL() mCamera.setTarget(Vector3f(0, 0, 0)); mInitFrame.orientation = mCamera.orientation().inverse(); mInitFrame.position = mCamera.viewMatrix().translation(); - - // create a kind of fractal sphere - { - IcoSphere pattern; - - int levels = 3; - float scale = 0.45; - float radius = 100; - std::vector<Vector3f> centers; - std::vector<int> parents; - std::vector<float> radii; - centers.push_back(Vector3f::Zero()); - parents.push_back(-1); - radii.push_back(radius); - radius *= scale; - - // generate level 1 using icosphere vertices - { - float dist = radii[0]*0.9; - for (int i=0; i<12; ++i) - { - centers.push_back(pattern.vertices()[i] * dist); - radii.push_back(radius); - parents.push_back(0); - } - } - - scale = 0.33; - static const float angles [10] = { - 0, 0, - M_PI, 0.*M_PI, - M_PI, 0.5*M_PI, - M_PI, 1.*M_PI, - M_PI, 1.5*M_PI}; - - // generate other levels - int start = 1; - float maxAngle = M_PI/2; - for (int l=1; l<levels; l++) - { - radius *= scale; - int end = centers.size(); - for (int i=start; i<end; ++i) - { - Vector3f c = centers[i]; - Vector3f ax0, ax1; - if (parents[i]==-1) - ax0 = Vector3f::UnitZ(); - else - ax0 = (c - centers[parents[i]]).normalized(); - ax1 = ax0.unitOrthogonal(); - Quaternionf q; - q.setFromTwoVectors(Vector3f::UnitZ(), ax0); - Transform3f t = Translation3f(c) * q * Scaling3f(radii[i]+radius); - for (int j=0; j<5; ++j) - { - Vector3f newC = c + ( (AngleAxisf(angles[j*2+1], ax0) - * AngleAxisf(angles[j*2+0] * (l==1 ? 0.35 : 0.5), ax1)) * ax0)*(radii[i] + radius*0.8); - centers.push_back(newC); - radii.push_back(radius); - parents.push_back(i); - } - } - start = end; - maxAngle = M_PI/2; - } - parents.clear(); - // instanciate the geometry - { - const std::vector<int>& sphereIndices = pattern.indices(2); - std::cout << "instanciate geometry... (" << sphereIndices.size() * centers.size() << " vertices)\n"; - mVertices.reserve(sphereIndices.size() * centers.size()); - mNormals.reserve(sphereIndices.size() * centers.size()); - int end = centers.size(); - for (int i=0; i<end; ++i) - { - Transform3f t = Translation3f(centers[i]) * Scaling3f(radii[i]); - // copy vertices - for (unsigned int j=0; j<sphereIndices.size(); ++j) - { - Vector3f v = pattern.vertices()[sphereIndices[j]]; - mVertices.push_back(t * v); - mNormals.push_back(v); - } - } - } - } } void RenderingWidget::resizeGL(int width, int height) @@ -539,10 +537,7 @@ void RenderingWidget::resetCamera() Frame aux1 = mCamera.frame(); aux1.orientation = aux1.orientation.inverse(); aux1.position = mCamera.viewMatrix().translation(); - float rangle = AngleAxisf(aux0.orientation.inverse() * aux1.orientation).angle(); - if (rangle>M_PI) - rangle = 2.*M_PI - rangle; - float duration = rangle * 0.9; + float duration = aux0.orientation.angularDistance(aux1.orientation) * 0.9; if (duration<0.1) duration = 0.1; // put the camera at that time step: @@ -660,3 +655,4 @@ int main(int argc, char *argv[]) } #include "quaternion_demo.moc" + |