Browse Source

beachball example

Former-commit-id: c3b47c0b2201f2d7da5242b9956da8e2fb34a195
Alec Jacobson (jalec 11 years ago
parent
commit
03bf91a29c

+ 236 - 0
examples/beach-balls/BeachBall.cpp

@@ -0,0 +1,236 @@
+#include "BeachBall.h"
+
+
+#include <igl/draw_beach_ball.h>
+#include <igl/quat_to_mat.h>
+#include <igl/unproject_to_zero_plane.h>
+#include <igl/unproject.h>
+#include <igl/project.h>
+#include <igl/quat_mult.h>
+#include <igl/quat_conjugate.h>
+#include <igl/trackball.h>
+#include <igl/mat_to_quat.h>
+
+#include <OpenGL/GL.h>
+
+#include <iostream>
+#include <cmath>
+
+BeachBall::BeachBall():
+  radius(1),
+  is_hover(false),
+  is_down(false),
+  trackball_on(false),
+  down_x(-1),
+  down_y(-1)
+{
+  r[0]=r[1]=r[2]=0;r[3]=1;
+  t[0]=t[1]=t[2]=0;t[3]=0;
+}
+
+void BeachBall::pushmv() const
+{
+  glPushMatrix();
+  glLoadIdentity();
+  glMultMatrixd(mv);
+}
+void BeachBall::popmv() const
+{
+  glPopMatrix();
+}
+
+void BeachBall::push() const
+{
+  using namespace igl;
+  glPushMatrix();
+  // Translate to relative origin
+  glTranslated(t[0],t[1],t[2]);
+  // Rotate to relative orientation
+  double mat[4*4]; quat_to_mat(r,mat); glMultMatrixd(mat);
+}
+void BeachBall::pop() const
+{
+  glPopMatrix();
+}
+
+void BeachBall::draw()
+{
+  using namespace std;
+  using namespace igl;
+  // Keep track of relative identity (modelview) matrix at draw call
+  glGetDoublev(GL_MODELVIEW_MATRIX,mv);
+  push();
+  // Dim if hovered over
+  float ld[4];
+  glGetLightfv(GL_LIGHT0,GL_DIFFUSE,ld);
+  if(is_hover)
+  {
+    float ld_hover[4];
+    ld_hover[0] = 0.5*ld[0];
+    ld_hover[1] = 0.5*ld[1];
+    ld_hover[2] = 0.5*ld[2];
+    ld_hover[3] = 0.5*ld[3];
+    glLightfv(GL_LIGHT0,GL_DIFFUSE,ld_hover);
+  }
+  // Adjust scale only after setting origin
+  glPushMatrix();
+  glScaled(radius,radius,radius);
+  // draw oriented glyph 
+  draw_beach_ball();
+  // Pop scale
+  glPopMatrix();
+  // Reset lighting
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,ld);
+  // Reset relative identity
+  pop();
+}
+
+bool BeachBall::in(const int x,const int y) const
+{
+  using namespace igl;
+  using namespace std;
+  pushmv();
+  push();
+  // Now origin is center of object
+  double obj[3];
+  // Check if unprojected screen point is nearby
+  unproject_to_zero_plane(x,y, &obj[0], &obj[1], &obj[2]);
+  bool near = (obj[0]*obj[0] + obj[1]*obj[1] + obj[2]*obj[2])<radius*radius;
+  pop();
+  popmv();
+  return near;
+}
+
+bool BeachBall::hover(const int x,const int y)
+{
+  return is_hover = in(x,y);
+}
+
+bool BeachBall::down(const int x,const int y)
+{
+  using namespace std;
+  using namespace igl;
+  is_down = in(x,y);
+  if(is_down)
+  {
+    copy(r,r+4,down_r);
+    copy(t,t+4,down_t);
+    down_x = x;
+    down_y = y;
+    trackball_on = true;
+  }
+  return is_down;
+}
+
+bool BeachBall::drag(const int x,const int y)
+{
+  using namespace igl;
+  using namespace std;
+  if(!is_down)
+  {
+    return false;
+  }
+  if(trackball_on)
+  {
+    // Pick up origin location
+    pushmv();
+    push();
+    double origin[3];
+    project(0,0,0,&origin[0],&origin[1],&origin[2]);
+    pop();
+    popmv();
+    double rot[4];
+    int VP[4];
+    glGetIntegerv(GL_VIEWPORT,VP);
+    trackball<double>(
+      VP[2],
+      VP[3],
+      2,
+            (down_x-origin[0]+VP[2]/2),
+      VP[3]-(down_y-origin[1]+VP[3]/2),
+            (     x-origin[0]+VP[2]/2),
+      VP[3]-(     y-origin[1]+VP[3]/2),
+      rot);
+    {
+      // We've computed change in rotation according to this view:
+      // R = mv * r, R' = rot * (mv * r)
+      // But we only want new value for r:
+      // R' = mv * r'
+      // mv * r' = rot * (mv * r)
+      // r' = mv* * rot * sr * r
+      // Convert modelview matrix to quaternion
+      double sr_conj[4],scene_rot[4],t1[4],t2[4];
+      mat4_to_quat(mv,scene_rot);
+      //cout<<"::sr: "<<
+      //  BeachBall::scene_rot[0]<<" "<<
+      //  BeachBall::scene_rot[1]<<" "<<
+      //  BeachBall::scene_rot[2]<<" "<<
+      //  BeachBall::scene_rot[3]<<" "<<
+      //  endl;
+      //cout<<"  sr: "<<
+      //  scene_rot[0]<<" "<<
+      //  scene_rot[1]<<" "<<
+      //  scene_rot[2]<<" "<<
+      //  scene_rot[3]<<" "<<
+      //  endl;
+      // Normalize to unit quaternion (rotation only)
+      double len = 
+        sqrt(scene_rot[0]*scene_rot[0]+
+        scene_rot[1]*scene_rot[1]+
+        scene_rot[2]*scene_rot[2]+
+        scene_rot[3]*scene_rot[3]);
+      for(int j = 0;j<4;j++)
+      {
+        scene_rot[j] /= len;
+      }
+      // TODO: Just use Eigen::Quaterniond
+      quat_conjugate(scene_rot,sr_conj);
+      quat_mult<double>(sr_conj,rot,t1);
+      quat_mult<double>(t1,scene_rot,t2);
+      quat_mult<double>(t2,down_r,r);
+
+    }
+  }else
+  {
+    // We want that origin follows mouse move. First define plane we
+    // projecteing screen mouse movement to as perpendicular plan passing
+    // through this origin.
+    pushmv();
+    // down_t projected to screen to get depth value
+    double p[3];
+    project(down_t[0],down_t[1],down_t[2],&p[0],&p[1],&p[2]);
+    // unprojected down_x,down_y with down_t depth
+    double du[3];
+    unproject(down_x,down_y,p[2],&du[0],&du[1],&du[2]);
+    // unprojected x,y with down_t depth
+    double u[3];
+    unproject(x,y,p[2],&u[0], &u[1], &u[2]);
+    popmv();
+    // Then move this origin according to project mouse displacment
+    t[0] = down_t[0] + (u[0]-du[0]);
+    t[1] = down_t[1] + (u[1]-du[1]);
+    t[2] = down_t[2] + (u[2]-du[2]);
+  }
+  return is_down;
+}
+
+bool BeachBall::right_down(const int x,const int y)
+{
+  using namespace std;
+  using namespace igl;
+  is_down = in(x,y);
+  if(is_down)
+  {
+    copy(r,r+4,down_r);
+    copy(t,t+4,down_t);
+    down_x = x;
+    down_y = y;
+  }
+  return is_down;
+}
+
+bool BeachBall::up(const int /*x*/,const int /*y*/)
+{
+  trackball_on = false;
+  return is_down = false;
+}

+ 61 - 0
examples/beach-balls/BeachBall.h

@@ -0,0 +1,61 @@
+#ifndef BEACHBALL_H
+#define BEACHBALL_H
+class BeachBall
+{
+  public:
+    static double * scene_rot;
+  public:
+    // Rigid transformation: rotation as quaternion
+    double r[4];
+    // Rigid transformation: translation as quaternion
+    double t[4];
+    double radius;
+  protected:
+    bool is_hover;
+    bool is_down;
+    // trackball
+    bool trackball_on;
+    // Rigid transformation at down
+    double down_r[4];
+    double down_t[4];
+    // query position at down
+    int down_x;
+    int down_y;
+    // modelview matrix at draw 
+    double mv[16];
+  public:
+    BeachBall();
+    // Push the latest modelview matrix seen at draw time onto the stack
+    void pushmv() const;
+    // Pop the stack
+    void popmv() const;
+    // Push rigid transformation onto the stack
+    void push() const;
+    // Pop the stack
+    void pop() const;
+    // Draw and cache the modelview matrix
+    void draw();
+    // Return whether (x,y) in screenspace is "inside" (hitting)
+    bool in(const int x,const int y) const;
+    // Called on passive mouse move to (x,y)
+    //
+    // Return whether (x,y) is hovering over, set is_hover accordingly
+    bool hover(const int x,const int y);
+    // Called on mouse down at (x,y)
+    //
+    // Return whether (x,y) is down, set is_down accordingly
+    bool down(const int x,const int y);
+    // Called on mouse drag to (x,y)
+    //
+    // Returns whether still is_down
+    bool drag(const int x,const int y);
+    // Called on right mouse down at (x,y)
+    //
+    // Return whether (x,y) is down, set is_down accordingly
+    bool right_down(const int x,const int y);
+    // Called on mouse up at (x,y)
+    //
+    // Returns whether still is_down
+    bool up(const int x,const int y);
+};
+#endif

+ 49 - 0
examples/beach-balls/Makefile

@@ -0,0 +1,49 @@
+
+.PHONY: all
+
+# Shared flags etc.
+include ../../Makefile.conf
+
+all: obj example
+
+.PHONY: example
+
+CFLAGS=-g -std=c++11
+
+LIBIGL=../../
+LIBIGL_INC=-I$(LIBIGL)/include
+LIBIGL_LIB=-L$(LIBIGL)/lib -ligl
+
+EIGEN3_INC=-I/opt/local/include/eigen3 -I/opt/local/include/eigen3/unsupported
+
+ANTTWEAKBAR_INC=-I$(LIBIGL)/external/AntTweakBar/include
+ANTTWEAKBAR_LIB=-L$(LIBIGL)/external/AntTweakBar/lib -lAntTweakBar -framework AppKit
+
+MATLAB_INC=-I$(MATLAB)/extern/include/
+MATLAB_LIB=-L$(MATLAB)/bin/maci64 -lmx -lmat -lmex -lstdc++
+
+# Use free glut for mouse scrolling
+GLUT_LIB=-framework GLUT
+GLUT_INC=-framework GLUT
+
+INC=$(LIBIGL_INC) $(ANTTWEAKBAR_INC) $(EIGEN3_INC) $(GLUT_INC)
+LIB=$(OPENGL_LIB) $(GLUT_LIB) $(ANTTWEAKBAR_LIB) $(LIBIGL_LIB)
+
+CPP_FILES=$(wildcard ./*.cpp)
+OBJ_FILES=$(addprefix obj/,$(notdir $(CPP_FILES:.cpp=.o))) 
+
+example: obj $(OBJ_FILES)
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -o example $(OBJ_FILES) $(LIB)
+
+obj:
+	mkdir -p obj
+
+obj/%.o: %.cpp
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+obj/%.o: %.cpp %.h
+	g++ $(OPENMP) $(AFLAGS) $(CFLAGS) -c $< -o $@ $(INC)
+
+clean:
+	rm -f $(OBJ_FILES)
+	rm -f example

+ 272 - 0
examples/beach-balls/example.cpp

@@ -0,0 +1,272 @@
+#include "BeachBall.h"
+
+#include <igl/quat_to_mat.h>
+#include <igl/report_gl_error.h>
+#include <igl/trackball.h>
+#include <igl/canonical_quaternions.h>
+#include <igl/PI.h>
+
+#include <GLUT/GLUT.h>
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <cmath>
+
+double back[3] = {85.0/255.0,85.0/255.0,85.0/255.0};
+double width,height;
+double scene_rot[4] = {0,0,0,1};
+double * BeachBall::scene_rot = NULL;
+double down_scene_rot[4] = {0,0,0,1};
+int down_mouse_x=-1,down_mouse_y=-1;
+bool trackball_on = false;
+const float light_pos[4] = {-0.2, -0.1, 1,0};
+
+std::vector<BeachBall> balls;
+float plane[4] = {0,0,1,1.5};
+
+int display_count = 0;
+
+void push_scene()
+{
+  using namespace igl;
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  //gluOrtho2D(0,width,0,height);
+  gluPerspective(15,(double)width/(double)height,1e-2,300);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+  glPushMatrix();
+  gluLookAt(0,0,20,0,0,0,0,1,0);
+  double mat[4*4];
+  quat_to_mat(scene_rot,mat);
+  glMultMatrixd(mat);
+}
+
+void lights()
+{
+  using namespace std;
+  using namespace igl;
+
+  glEnable(GL_LIGHTING);
+  float ones[4] = {1.0,1.0,1.0,1.0};
+  glLightfv(GL_LIGHT0,GL_AMBIENT,ones);
+  glLightfv(GL_LIGHT0,GL_DIFFUSE,ones);
+  glLightfv(GL_LIGHT0,GL_SPECULAR,ones);
+  glLightfv(GL_LIGHT0,GL_POSITION,light_pos);
+  glEnable(GL_LIGHT0);
+}
+
+void pop_scene()
+{
+  glPopMatrix();
+}
+
+void display()
+{
+  using namespace std;
+  using namespace igl;
+
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  if(true || display_count==0 || display_count==200)
+  {
+    glClearColor(back[0],back[1],back[2],0);
+    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+    glEnable(GL_DEPTH_TEST);
+    
+    lights();
+    push_scene();
+
+    //// Normal list
+    //for(int i = 0;i<(int)balls.size();i++)
+    //{
+    //  balls[i].draw();
+    //}
+
+    // single root
+    balls[0].draw();
+    balls[0].push();
+    for(int i = 1;i<(int)balls.size();i++)
+    {
+      balls[i].radius = 0.5;
+      balls[i].draw();
+    }
+    balls[0].pop();
+
+  // Draw floor
+    glEnable(GL_COLOR_MATERIAL);
+    glEnable(GL_POLYGON_OFFSET_FILL);
+    glPolygonOffset(10.0,1);
+    float size = 10;
+    glBegin(GL_QUADS);
+    glNormal3f(0,0,1);
+    glColor4f(0,0.2,0.8,0.5);
+    glVertex4f(-size,-size,-plane[3],1);
+    glColor4f(0,0,1,0.5);
+    glVertex4f( size,-size,-plane[3],1);
+    glColor4f(0.0,0.1,0.5,0.5);
+    glVertex4f( size, size,-plane[3],1);
+    //glColor4f(back[0],back[1],back[2],1);
+    glColor4f(0.0,0.1,0.5,0.5);
+    glVertex4f(-size, size,-plane[3],1);
+    glEnd();
+    glDisable(GL_POLYGON_OFFSET_FILL);
+    pop_scene();
+  }
+
+
+  //// Animation
+  //for(int i = 0;i<(int)balls.size();i++)
+  //{
+  //  balls[i].r[0] += cos(double(i*display_count)/1000.0) + sin(double(display_count)/1000.0);
+  //  balls[i].r[1] += sin(double(2*i*display_count)/1000.0) + cos(double(2*display_count)/1000.0);
+  //  balls[i].r[2] += cos(double(3*i*display_count)/1000.0) + sin(double(3*display_count)/1000.0);
+  //  balls[i].r[3] += sin(double(4*i*display_count)/1000.0) + cos(double(4*display_count)/1000.0);
+  //  double len = 
+  //    sqrt(balls[i].r[0]*balls[i].r[0]+
+  //    balls[i].r[1]*balls[i].r[1]+
+  //    balls[i].r[2]*balls[i].r[2]+
+  //    balls[i].r[3]*balls[i].r[3]);
+  //  for(int j = 0;j<4;j++)
+  //  {
+  //    balls[i].r[j] /= len;
+  //  }
+  //}
+
+  report_gl_error();
+  glutSwapBuffers();
+  glutPostRedisplay();
+
+  display_count++;
+}
+
+void reshape(int width, int height)
+{
+  using namespace std;
+  ::width = width;
+  ::height = height;
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glViewport(0,0,width,height);
+}
+
+void key(unsigned char key, int /*mouse_x*/, int /*mouse_y*/)
+{
+  using namespace std;
+
+  switch(key)
+  {
+    case char(27):
+      exit(0);
+    default:
+      cout<<"Unknown key command: "<<key<<" "<<int(key)<<endl;
+  }
+}
+
+void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
+{
+  mouse_y = height-mouse_y;
+  using namespace std;
+  push_scene();
+  if(glutState==1)
+  {
+    for(int i = 0;i<(int)balls.size();i++)
+    {
+      balls[i].up(mouse_x,mouse_y);
+      balls[i].hover(mouse_x,mouse_y);
+    }
+    trackball_on = false;
+  }else if(glutState==0)
+  {
+    // down
+    bool any = false;
+    for(int i = 0;!any && i<(int)balls.size();i++)
+    {
+      if(glutButton==0)
+      {
+        any |= balls[i].down(mouse_x,mouse_y);
+      }else if(glutButton==2)
+      {
+        any |= balls[i].right_down(mouse_x,mouse_y);
+      }
+    }
+    trackball_on = !any;
+    copy(scene_rot,scene_rot+4,down_scene_rot);
+    down_mouse_x = mouse_x;
+    down_mouse_y = mouse_y;
+  }
+  pop_scene();
+}
+
+void mouse_drag(int mouse_x, int mouse_y)
+{
+  mouse_y = height-mouse_y;
+  using namespace std;
+  using namespace igl;
+  if(trackball_on)
+  {
+    trackball<double>(
+      width,
+      height,
+      2,
+      down_scene_rot,
+      down_mouse_x,
+      height-down_mouse_y,
+      mouse_x,
+      height-mouse_y,
+      scene_rot);
+  }
+  push_scene();
+  for(int i = 0;i<(int)balls.size();i++)
+  {
+    balls[i].drag(mouse_x,mouse_y);
+  }
+  pop_scene();
+
+}
+
+void mouse_move(int mouse_x, int mouse_y)
+{
+  mouse_y = height-mouse_y;
+  push_scene();
+  bool any = false;
+  for(int i = 0;!any && i<(int)balls.size();i++)
+  {
+    any |= balls[i].hover(mouse_x,mouse_y);
+  }
+  pop_scene();
+}
+
+
+int main(int argc,char * argv[])
+{
+  using namespace igl;
+  using namespace std;
+  glutInit(&argc,argv);
+  glutInitDisplayString( "rgba depth double samples>=8 ");
+  glutInitWindowSize(glutGet(GLUT_SCREEN_WIDTH),glutGet(GLUT_SCREEN_HEIGHT)/2);
+  glutCreateWindow(__FILE__);
+  glutDisplayFunc(display);
+  glutReshapeFunc(reshape);
+  glutKeyboardFunc(key);
+  glutMouseFunc(mouse);
+  glutMotionFunc(mouse_drag);
+  glutPassiveMotionFunc(mouse_move);
+
+  //copy(XZ_PLANE_QUAT_D,XZ_PLANE_QUAT_D+4,scene_rot);
+
+  balls.push_back(BeachBall());
+  const int children = 10;
+  for(int i = 1;i<=children;i++)
+  {
+    balls.push_back(BeachBall());
+    balls[i].t[0] = 2.5*sin(double(i)*2.0*PI/double(children));
+    balls[i].t[1] = 2.5*cos(double(i)*2.0*PI/double(children));
+  }
+  BeachBall::scene_rot = scene_rot;
+
+  glutMainLoop();
+  return 0;
+}

+ 1 - 0
examples/transparency/Makefile

@@ -13,6 +13,7 @@ LIBIGL_INC=-I$(LIBIGL)/include
 LIBIGL_LIB=-L$(LIBIGL)/lib -ligl -liglmatlab -liglembree
 
 EIGEN3_INC=-I/opt/local/include/eigen3 -I/opt/local/include/eigen3/unsupported
+CFLAGS+=-O3 -fopenmp
 
 ANTTWEAKBAR_INC=-I$(LIBIGL)/external/AntTweakBar/include
 ANTTWEAKBAR_LIB=-L$(LIBIGL)/external/AntTweakBar/lib -lAntTweakBar -framework AppKit

+ 1 - 1
examples/transparency/example.cpp

@@ -155,7 +155,7 @@ void mouse(int glutButton, int glutState, int mouse_x, int mouse_y)
       // sort!
       push_scene();
       push_object();
-      sort_triangles_robust(V,F,sorted_F,I);
+      sort_triangles(V,F,sorted_F,I);
       slice(N,I,1,sorted_N);
       init_C(I);
       pop_object();