2017年11月30日 星期四

LYC的計圖學習筆記-WEEK12

GLUT可以同時開好幾個視窗

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

float rrr=0;

GLUquadric* quadFrustrum=NULL;
float rot=0;
float rotX=30, rotY=-30;
float bigger=2;
bool bOrtho=false, bShow1=true, bShow2=true;
int winW=600, winH=400, winTitleH=30;
int winID[4];

float blendPercent=0.5;
float K1x=200,K1y=50,K1z=200, K2x=-50,K2y=50,K2z=50;
float K1cx=-200,K1cy=-200,K1cz=500, K2cx=0,K2cy=-200,K2cz=500;
void frustrum(float r, float g, float b, float a);

float humanX=0, humanY=0;
void showHuman1();
void showHuman2();

typedef struct _myPoint{
float x, y, z;
} myPoint;
myPoint human1[15]={//我這座標是亂設的, 請即時地把 OpenNI 量到的值塞進來即可
{0,0,1.5}, {0,0.3,1.5}, {0,0.9,1.3},
{0.2, 0.3, 1.5}, {0.4, 0.3, 1.5}, {0.8, 0.3,1.5},
{-0.2,0.3, 1.5}, {-0.4,0.3, 1.5}, {-0.8,0.3,1.5},
{0.2, -0.2,1.5}, {0.2,-0.6, 1.5}, {0.2,-1,1.5},
{-0.2,-0.2,1.5}, {-0.2,-0.6,1.5}, {-0.2,-1,1.5}};
myPoint human2[15]={//我這座標是亂設的, 請即時地把 OpenNI 量到的值塞進來即可
{0,0,1.5}, {0,0.3,1.5}, {0,0.9,1.3},
{0.2, 0.3, 1.5}, {0.6, 0.3, 1.5}, {0.8, 0.3,1.5},
{-0.2,0.3, 1.5}, {-0.6,0.3, 1.5}, {-0.8,0.3,1.5},
{0.2, -0.2,1.5}, {0.2,-0.6, 1.5}, {0.2,-1,1.5},
{-0.2,-0.2,1.5}, {-0.2,-0.6,1.5}, {-0.2,-1,1.5}};
void showHuman1()
{
//TO Show Human, you can use human1[] 將座標 放到陣列中,即可自動秀出
glColor3f(0.5,0.5,0);
for(int i=0;i<15;i++){//小心,關節數量要正確,這裡是15
glPushMatrix();
glTranslatef(human1[i].x, human1[i].y, -1*human1[i].z);//小心,z為負
glutSolidSphere(0.1,10,10);
glPopMatrix();
}
}
void showHuman2()
{
//TO Show Human, you can use human2[] 將座標 放到陣列中,即可自動秀出
glColor3f(0,0.5,0);
for(int i=0;i<15;i++){
glPushMatrix();
glTranslatef(human2[i].x, human2[i].y, -1*human2[i].z);//小心,z為負
glutSolidSphere(0.1,10,10);
glPopMatrix();
}
}

void NormalizeVector(float v[3])
{
float len=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
v[0]/=len;
v[1]/=len;
v[2]/=len;
}
void ComputeNormalOfPlane(float ans[3], float v1[3], float v2[3])
{
ans[0]=v1[1]*v2[2]-v1[2]*v2[1];
ans[1]=v1[2]*v2[0]-v1[0]*v2[2];
ans[2]=v1[0]*v2[1]-v1[1]*v2[0];
}
void myLookAtRotate(float ex, float ey, float ez, float cx, float cy, float cz, float upx, float upy, float upz)
{
float forward[3], side[3], up[3];
float matrix2[16], resultMatrix[16];
//------------------
forward[0] = cx-ex;
forward[1] = cy-ey;
forward[2] = cz-ez;
NormalizeVector(forward);
up[0]=upx; up[1]=upy; up[2]=upz;
//------------------
//Side = forward x up
ComputeNormalOfPlane(side, forward, up);
NormalizeVector(side);
//------------------
//Recompute up as: up = side x forward
ComputeNormalOfPlane(up, side, forward);
//------------------
matrix2[0] = side[0];
matrix2[4] = side[1];
matrix2[8] = side[2];
matrix2[12] = 0.0;
//------------------
matrix2[1] = up[0];
matrix2[5] = up[1];
matrix2[9] = up[2];
matrix2[13] = 0.0;
//------------------
matrix2[2] = -forward[0];
matrix2[6] = -forward[1];
matrix2[10] = -forward[2];
matrix2[14] = 0.0;
//------------------
matrix2[3] = matrix2[7] = matrix2[11] = 0.0;
matrix2[15] = 1.0;
//下面是我亂試的!

matrix2[0] = side[0];
matrix2[1] = side[1];
matrix2[2] = side[2];
matrix2[3] = 0.0;
//------------------
matrix2[4] = up[0];
matrix2[5] = up[1];
matrix2[6] = up[2];
matrix2[7] = 0.0;
//------------------
matrix2[8] = -forward[0];
matrix2[9] = -forward[1];
matrix2[10] = -forward[2];
matrix2[11] = 0.0;
//------------------
matrix2[12] = matrix2[13] = matrix2[14] = 0.0;

glMultMatrixf(matrix2);
}
void room()
{
glEnable(GL_DEPTH_TEST);

glPushMatrix();
glScalef(400,400,500);
glTranslatef(0,0,0.5);//鍾老師的坐標系統是左手標系統(類kinect)會有問題
glColor4f(0.9,0.9,0.9,0.9);
glutSolidCube(1);//The blending room
glDisable(GL_DEPTH_TEST);
glEnable(GL_LINE_STIPPLE);//dashed line
glColor3f(0,0,0);
glutWireCube(1);//The edge of the room (Hidden line, black)
glDisable(GL_LINE_STIPPLE);
glEnable(GL_DEPTH_TEST);
glColor3f(1,0,0);
glutWireCube(1.005);//The edge of the room (Visible line, red)

glTranslatef(0,-0.52,0);
glScalef(1.5,0.01,1.5);
glColor3f(1,1,1);
glutSolidCube(1);//The big floor
glDisable(GL_DEPTH_TEST);
glEnable(GL_LINE_STIPPLE);//dashed line
glColor3f(0,0,0);
glutWireCube(1);//The edge of the big floor (Hidden line, black)
glDisable(GL_LINE_STIPPLE);
glEnable(GL_DEPTH_TEST);
glColor3f(1,0,0);
glutWireCube(1);//The edge of the big floor (Visible line, red)

glPopMatrix();

glDisable(GL_DEPTH_TEST);
glColor3f(0,0,0);
glEnable(GL_LINE_STIPPLE);//dashed line
glBegin(GL_LINE_LOOP);//Window
glVertex3f(180,150,500);
glVertex3f(180,-150,500);
glVertex3f(-50,-150,500);
glVertex3f(-50,150,500);
glEnd();
glDisable(GL_LINE_STIPPLE);

glEnable(GL_DEPTH_TEST);
glColor3f(1,0,0);
glBegin(GL_LINE_LOOP);//Window
glVertex3f(180,150,502);
glVertex3f(180,-150,502);
glVertex3f(-50,-150,502);
glVertex3f(-50,150,502);
glEnd();

glClear(GL_DEPTH_BUFFER_BIT);
if(bShow1){
glPushMatrix();
glTranslatef(K1x,K1y,K1z);
glColor3f(0.9,0.5,0);//dark yellow
glutSolidSphere(5,10,10);//EYE 1
glScalef(100,100,100);
myLookAtRotate(K1x,K1y,K1z, K1cx,K1cy,K1cz, 0,1,0);
frustrum(1,1,0,blendPercent);//Kinect 1 (yellow)
glPopMatrix();
glPushMatrix();
glTranslatef(K1cx,K1cy,K1cz);
glutSolidSphere(5,10,10);//Kinect 1 看的目標  -2,-2,5
glPopMatrix();
}else{
// glDisable(GL_DEPTH_TEST);
// glPushMatrix();
// glTranslatef(K1x,K1y,K1z);
// glScalef(100,100,100);
// myLookAtRotate(K1x,K1y,K1z, K1cx,K1cy,K1cz, 0,1,0);
// showHuman1();//將第1台Kinect裡的使用者秀出來
// glPopMatrix();
// glEnable(GL_DEPTH_TEST);
}

glClear(GL_DEPTH_BUFFER_BIT);
if(bShow2){
glPushMatrix();
glTranslatef(K2x,K2y,K2z);
glColor3f(0,0.5,0);//dark green
glutSolidSphere(5,10,10);//EYE 2
glScalef(100,100,100);
myLookAtRotate(K2x,K2y,K2z, K2cx,K2cy,K2cz, sin(rrr),cos(rrr),0);//2012-12-17 rotating the camera by the UP vector
frustrum(0.5,1,0.5,blendPercent);//Kinect 2 (green)
glPopMatrix();
glPushMatrix();
glTranslatef(K2cx,K2cy,K2cz);
glutSolidSphere(5,10,10);//Kinect 2看的目標 0,-2,5
glPopMatrix();
}else{
// glPushMatrix();
// glTranslatef(K2x,K2y,K2z);
// glScalef(100,100,100);
// myLookAtRotate(K2x,K2y,K2z, K2cx,K2cy,K2cz, 0,1,0);//2012-12-17 don't rotate the camera UP vector for the small green man
// glDisable(GL_DEPTH_TEST);
// showHuman2();//將第2台Kinect裡的使用者秀出來
// glEnable(GL_DEPTH_TEST);
// glPopMatrix();
}

// glColor3f(0,0,0);
// glutSolidSphere(2,10,10);//original center

glDisable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(humanX,-100,humanY);
glScalef(100,100,-100);
showHuman1();
glPopMatrix();
glEnable(GL_DEPTH_TEST);

glEnable(GL_CULL_FACE);//special floor
glColor3f(0.5,0.5,0.5);
glBegin(GL_POLYGON);
glScalef(400,400,500);
glVertex3f(300,-210,625);
glVertex3f(300,-210,-125);
glVertex3f(-300,-210,-125);
glVertex3f(-300,-210,625);
glEnd();
glDisable(GL_CULL_FACE);

}

void frustrum(float r, float g, float b, float a)
{
glPushMatrix();
glScalef(3,3,3);
//http://stackoverflow.com/questions/7696436/precision-of-the-kinect-depth-camera
//62.0 vs. 48.6 (color) and 58.5 vs. 45.6 (depth)
//old kinect spec: 57 vs. 43
glScalef(tan(58.5*M_PI/180/2.0),tan(45.6*M_PI/180/2.0),1);
glScalef(1,1,1);
glTranslatef(0,0,-1);
glRotatef(45,0,0,1);

glColor4f(1,0,0,0.5);
gluQuadricDrawStyle(quadFrustrum,GLU_LINE);
gluCylinder(quadFrustrum, sqrt(2), 0, 1, 4, 1);
glColor4f(r,g,b,a);
gluQuadricDrawStyle(quadFrustrum,GLU_FILL);
gluCylinder(quadFrustrum, sqrt(2), 0, 1, 4, 1);
glBegin(GL_POLYGON);
glVertex3f(sqrt(2),0, 0);
glVertex3f(0,sqrt(2), 0);
glVertex3f(-sqrt(2),0,0);
glVertex3f(0,-sqrt(2),0);
glEnd();
glPopMatrix();
}
void displayOrtho()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_TEXTURE_2D);

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);

glPushMatrix();
glScalef(bigger, bigger, bigger);
glScalef(0.001, 0.001, 0.001);

glTranslatef(0,0,-250);//(400,350,500);
glScalef(-1,1,1);//GL的右手座標系統,與Kinect左手座標系統不同

room();//之後就都用Kinect左手座標系統沒關係,反正z都會被我轉成負的

glPopMatrix();
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);

glutSwapBuffers();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_TEXTURE_2D);

glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);

glPushMatrix();
glScalef(bigger, bigger, bigger);
glRotatef(rotY, 1,0,0);
glRotatef(rotX, 0,1,0);
glScalef(0.001, 0.001, 0.001);

glTranslatef(0,0,-250);//(400,350,500);
glScalef(-1,1,1);//GL的右手座標系統,與Kinect左手座標系統不同

room();//之後就都用Kinect左手座標系統沒關係,反正z都會被我轉成負的

glPopMatrix();
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);

glutSwapBuffers();
}
void resizeTop(int w, int h)
{
winW=w;winH=h;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1.0*h/w,1.0*h/w,-10,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,2,0,0,0,0,0,0,1);
}
void resizeFront(int w, int h)
{
winW=w;winH=h;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1.0*h/w,1.0*h/w,-10,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,-2,0,0,0,0,1,0);
}
void resizeSide(int w, int h)
{
winW=w;winH=h;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1,1,-1.0*h/w,1.0*h/w,-10,10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(2,0,0,0,0,0,0,1,0);
}
void resize(int w, int h)
{
winW=w;winH=h;
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(bOrtho){

glOrtho(-1,1,-1.0*h/w,1.0*h/w,-10,10);
}else{
gluPerspective(57, w/(float)h, 0.1f, 3000.0f);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0,0,-2,0,0,0,0,1,0);
}
void timer(int t)
{
glutTimerFunc(33,timer, t+1);
for(int i=0;i<4;i++){
glutSetWindow(winID[i]);
glutPostRedisplay();
}
}
int oldx=0,oldy=0;
void mouse(int button, int state, int x, int y)
{
if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN){
oldx=x;oldy=y;
}else if(button==GLUT_LEFT_BUTTON && state==GLUT_UP){

}
}
void motion(int x, int y)
{
rotX+=(x-oldx)/2;
rotY-=(y-oldy)/2;
oldx=x;oldy=y;
}
void keyboard(unsigned char key, int x, int y)
{
if(key==27){
exit(0);
}else if(key=='+' || key=='='){
bigger*=1.1;
}else if(key=='-'){
bigger*=0.9;
}else if(key=='o' || key=='O'){
bOrtho= !bOrtho; //true
resize(winW, winH);
}else if(key=='p' || key=='P'){
bOrtho= !bOrtho; //false;
resize(winW, winH);
}else if(key=='1'){
bShow1=!bShow1;
}else if(key=='2'){
bShow2=!bShow2;
}else if(key=='9'){
rrr+=0.1;
}else if(key=='a' || key=='A'){
humanX--;
}else if(key=='d' || key=='D'){
humanX++;
}else if(key=='w' || key=='W'){
humanY++;
}else if(key=='s' || key=='S'){
humanY--;
}else if(key=='b' || key=='B'){
if(blendPercent>0.5) blendPercent=0.5;
else blendPercent=1;
}
glutPostRedisplay();
}
void special(int key, int x, int y)
{
if(key==GLUT_KEY_LEFT)rotX+=2;
if(key==GLUT_KEY_RIGHT) rotX-=2;
if(key==GLUT_KEY_UP) rotY-=2;
if(key==GLUT_KEY_DOWN) rotY+=2;
}
void mySetCallback()
{
glutKeyboardFunc(keyboard);
glutSpecialFunc(special);
glClearColor(1,1,1,1);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void initGL()
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGBA);
glutInitWindowSize(winW, winH);

winID[0]=glutCreateWindow("Top View");
mySetCallback();
glutPositionWindow(winW+30,0+winTitleH);
glutDisplayFunc(displayOrtho);
glutReshapeFunc(resizeTop);

winID[1]=glutCreateWindow("Side View");
mySetCallback();
glutPositionWindow(0+10,winH+winTitleH*2);
glutDisplayFunc(displayOrtho);
glutReshapeFunc(resizeSide);

winID[2]=glutCreateWindow("Front View");
mySetCallback();
glutPositionWindow(winW+30,winH+winTitleH*2);
glutDisplayFunc(displayOrtho);
glutReshapeFunc(resizeFront);

winID[3]=glutCreateWindow("3D展示程式-鍾聖倫老師 v2.2, (c)2012 by jsyeh 2012-12-21");
glutPositionWindow(0+10,0+winTitleH);
mySetCallback();
glutDisplayFunc(display);
glutReshapeFunc(resize);
glutMouseFunc(mouse);
glutMotionFunc(motion);

glutTimerFunc(0, timer, 0);

quadFrustrum=gluNewQuadric();
glLineStipple(1,0x0101);
}
void readKinectCFG()
{
FILE * fin=fopen("myGL_Frustrum.txt", "r");
if(fin!=NULL){
fscanf(fin, "%f %f %f", &K1x, &K1y, &K1z);
fscanf(fin, "%f %f %f", &K1cx, &K1cy, &K1cz);
fscanf(fin, "%f %f %f", &K2x, &K2y, &K2z);
fscanf(fin, "%f %f %f", &K2cx, &K2cy, &K2cz);
}
fclose(fin);
}
int main(int argc,char *argv[])
{
    glutInit(&argc,argv);
printf("Usage\n"
"(1) Mouse Drag to rotate\n"
"(2) Key UP/DOWN/LEFT/RIGHT to rotate\n"
"(3) Key '+'/'-' to resize\n"
"(4) Key 'o' for Orthogonal Projection\n"
"(5) Key 'p' for Perspective Projection\n"
"(6) Key '1'(red ball) and '2'(green ball) to switch to Kinect Frustrum\n"
"(7) Key ASDW for (humanX, humanY) movememt\n"
"It will read myGL_Frustrum.txt for Kinect Positions and Targets");
readKinectCFG();
initGL();
glutMainLoop();
return 0;
}

用樹狀結構以關節為基畫出人體動作

float [][]frames;
int frameN;
float frameTime;
class Bone{
  ArrayList<Bone> childs;
  PVector offset;
  int r0;//address/index of Zrotation Xrotation Yrotatioin
  int cN;//channels number
  String name;
  Bone(String _name, PVector _offset, int _r0, int _cN){
    childs=new ArrayList<Bone>();
    name=_name;
    offset=_offset;
    r0=_r0;
    cN=_cN;
  }
  void showTree(){
    println(name);
    println("offset:"+offset);
    println("r0:"+r0);
    println("{");
    for(Bone b:childs){
      b.showTree();
    }
    println("}");
  }
  void draw(int i){
    if(name=="End Site"){
      pushMatrix();
      beginShape(LINES);
      vertex(0,0,0);
      vertex(offset.x, offset.y, offset.z);
      endShape();
      popMatrix();
      return;
    }
    pushMatrix();
    rotateZ(radians(frames[i][r0]));
    rotateX(radians(frames[i][r0+1]));
    rotateY(radians(frames[i][r0+2]));
    ellipse(0,0,10,10);
    beginShape(LINES);
    vertex(0,0,0);
    vertex(offset.x, offset.y, offset.z);
    endShape();
    translate(offset.x, offset.y, offset.z);
    for(Bone b: childs){
      b.draw(i);
    }
    popMatrix();
  }
}
Bone root;
void setup() {
  size(600, 400, P3D);
  loadBVH("watch.bvh");
  root.showTree();
  println("frameN"+frameN);
}
String getName(String line){
  String [] words=splitTokens(line);
  return words[1];
}
PVector getOffset(String line){
  String [] words=splitTokens(line);
  PVector now=new PVector(float(words[1]), float(words[2]), float(words[3]) );
  return now;
}
int getChannelsN(String line){
  String [] words=splitTokens(line);
  return int(words[1]);
}
int parseNode(String [] lines, int i, Bone parent){
  if(level==0)return i;
  while(true){
    if (lines[i].indexOf("JOINT")!=-1) {
      String name = getName(lines[i]);
      PVector offset = getOffset(lines[i+2]);
      int cN=getChannelsN(lines[i+3]);
      Bone now=new Bone(name, offset, channelN, cN);
      parent.childs.add(now);
      channelN+=cN;
      i+=3;
      level++;
      println("JOINT "+name);
      i=parseNode(lines, i+1, now);
    } else if (lines[i].indexOf("End Site")!=-1) {
      String name="End Site";
      PVector offset = getOffset(lines[i+2]);
      Bone now=new Bone(name, offset, 0, 0);
      parent.childs.add(now);
      i+=4;
      println("End Site");
    } else if (lines[i].indexOf("}")!=-1) {
      level--;
      return i+1;
    }else println("Error:"+lines[i]);
  }
}
int level=0, channelN=0;
void loadBVH(String filename) {
  int motionI=0;
  String [] lines=loadStrings(filename);
  for (int i=0; i<lines.length; i++) {
    println(lines[i]);
    if ( lines[i].equals("HIERARCHY") ){
      i++;
      if (lines[i].indexOf("ROOT")!=-1) {
        String name = getName(lines[i]);
        PVector offset = getOffset(lines[i+2]);
        int cN=getChannelsN(lines[i+3]);
        root=new Bone(name, offset, channelN, cN);
        channelN+=cN;
        i+=3;
        level++;
        println("ROOT "+name);
        i=parseNode(lines, i+1, root)-1;
      }
    }else if (lines[i].equals("MOTION") ){
      println(lines[i+1].substring(12));
      frameN=int(lines[i+1].substring(12));
      frameTime=float(lines[i+1].substring(12));
      motionI=i+3;
      println(motionI);
      break;
    }
  }
  frames = new float[frameN][channelN];
  for(int i=0;i<frameN;i++){
    String [] v=splitTokens(lines[motionI+i]);
    for(int j=0;j<channelN;j++){
      frames[i][j]=float(v[j]);
    }
  }
}
void draw() {
  background(255);
  translate(width/2, height/2);
  rotateX(PI/2);
  int i=800+frameCount%(frameN-800);
  translate(frames[i][0], frames[i][1], frames[i][2]);
  root.draw(i);
  println(i);
}

沒有留言:

張貼留言