2021年3月31日 星期三

電腦圖學筆記-week06

 1.將上週的萬花尺程式做改良


PImage imgBG;

PGraphics pg;

//https://gentlejourneysbirthing.com/home/colorful_watercolor_texture_by_connyduck-d6o409f/

ArrayList<PVector> points;

void setup(){

  size(800,600,P2D);  

  stroke(255);

  noFill();

  points = new ArrayList<PVector>();

  angle = atan2(-cy, -cx);

  imgBG=loadImage("watercolor_texture.png");

  pg = createGraphics(800,600);

  drawPG();

}

float r0=225, r1=57, r2=37.3;

float cx=320, cy=240;

float angle;

void drawPG(){

  pg.beginDraw();

  pg.noFill();

  pg.strokeWeight(2);

  pg.stroke(255);

  pg.beginShape();

  int a = points.size();

  if(a>2){

    pg.vertex(points.get(a-2).x, points.get(a-2).y);

    pg.vertex(points.get(a-1).x, points.get(a-1).y);

  }//只畫最後的點,前面不用再畫,可能會快一點

/*  for( PVector pt : points ){

    pg.vertex(pt.x, pt.y);//之後可變彩色漸層色彩

  }*/

  pg.endShape();

  pg.endDraw();

}

void draw(){

  background(0);

  imgBG.mask(pg);

  image(imgBG,0,0);

  colorMode(RGB);

  stroke(128);

  strokeWeight(1);

  ellipse(cx,cy, r0*2, r0*2);

  angle += deltaAngle();

  float angle2= -angle * r0 / r1;

  float x=cx+(r0-r1)*cos(angle), y=cy+(r0-r1)*sin(angle);

  //line(cx,cy, x, y);//不要畫線,比較好看

  circle2(x,y, r1, angle2);

  //if(mousePressed) saveFrame();

}

void circle2(float cx, float cy, float r, float angle){

  ellipse(cx,cy, r*2, r*2);

  for(float a=angle; a<angle+PI*2;a+=PI/4){

    line(cx,cy, cx+r*cos(a), cy+r*sin(a));

  }

}

float deltaAngle(){

  float angleNow=atan2(mouseY-cy,mouseX-cx);

  float angleOld=atan2(pmouseY-cy,pmouseX-cx);

  float delta = angleNow - angleOld;

  if( abs(delta)> PI ){

    if(delta>0) delta-=PI*2;

    else delta += PI*2;

  }

  return delta;

}

void mouseDragged(){//按下mouse才開始記錄點

  float angle2= -angle * r0 / r1;

  float x=cx+(r0-r1)*cos(angle), y=cy+(r0-r1)*sin(angle);  

  float x2=x+r2*cos(angle2), y2=y+r2*sin(angle2); 

  points.add( new PVector(x2,y2) );

  drawPG();

}

2.複習上周的程式,使畫線的程式用 keyboard會轉動

#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glColor3b(1,0,0);
    glPushMatrix();
    glRotatef(ang,0,0,1);
    glBegin(GL_LINE_LOOP);
    for(int i=0;i<n;i++){
        glVertex2f((vx[i]-150)/150.0,-(vy[i]-150)/150.0);
    }
    glEnd();
    glPopMatrix();
    glutSwapBuffers();
}
void mouseFunc(int x,int y)
{
    vx[n]=x;
    vy[n]=y;
    n++;
    display();
}
void keyb(unsigned char key,int x,int y)
{
    ang++;
    display();
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("GLUT Shapes");
    glutKeyboardFunc(keyb);
    glutDisplayFunc(display);
    glutMotionFunc(mouseFunc);
    glutMainLoop();
}


3.寫方塊會轉動的程式


#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //glColor3b(1,0,0);
    glPushMatrix();
        glRotatef(ang,0,0,1);
        glutSolidCube(1);
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);

    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}

 

4.寫長方形會轉動的程式

 

#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //
    glPushMatrix();
        glRotatef(ang,0,0,1);
        glScalef(0.5,0.1,0.1);
        glColor3f(1,0,1);
        glutSolidCube(1);
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}
5.AD 自動微分,用程式呈現鐘擺的效果

//https://matthias-research.github.io/pages/publications/posBasedDyn.pdf
//照著上面論文的演算法實作, 應該是 better PBD
int N=8;//vertex number頂點數量
PVector [] gradient=new PVector[N];
PVector [] pos=new PVector[N];
PVector [] pos0=new PVector[N];
PVector [] v=new PVector[N];
float d0=30, angle0=radians(0); 
boolean bSolving=true;
void setup(){
  size(500,500);
  for(int i=0;i<N;i++){
    pos[i]=new PVector( 150+i*30, 100);//new PVector(random(150,350),random(150,350));
    pos0[i]=new PVector( 150+i*30, 100);//new PVector(random(150,350),random(150,350));
    v[i] = new PVector();
    gradient[i]=new PVector();
  }
  genStretchBendingConstraint();
}
void printNAN(){
  for(int i=0; i<N; i++) print(pos[i]);
  println();
}
void myLine(PVector p1, PVector p2){
  line(p1.x,p1.y,p2.x,p2.y);
}
float Ci(int i, PVector [] pos){
  PVector ans=new PVector();
  for(int j=0;j<N;j++){//TODO: 變成N
    float w=a[i][j];
    ans.add( PVector.mult(pos[j], w) );
  }
  return ans.magSq()-d0*d0;
}
//float C1(PVector [] pos){//input: 3*pos
//  PVector v1 = PVector.sub(pos[1],pos[0]);
//  return v1.magSq()-d0*d0;
//}
//float C2(PVector [] pos){
//  PVector v2 = PVector.sub(pos[2],pos[1]);
//  return v2.magSq()-d0*d0;
//}
//int [][]b={
//  {1,0,2,1},
//  {2,1,3,2},
//  {3,2,4,3}
//};
//int [][]a={
//  {-1,1,0,0,0},
//  {0,-1,1,0,0},
//  {0,0,-1,1,0},
//  {0,0,0,-1,1} };
int [][]a;
int [][]b;
void genStretchBendingConstraint(){
  a = new int[N-1][N];
  for(int i=0;i<N-1;i++){
    for(int j=0;j<N;j++){
      if(i==j) a[i][j]=-1;
      else if(i+1==j) a[i][j]=1;
      else a[i][j]=0;
    }
  }
  b = new int[N-2][4];
  for(int i=0;i<N-2;i++){
    b[i][0]=i+1;
    b[i][1]=i;
    b[i][2]=i+2;
    b[i][3]=i+1;
  }
}
float Cbendi(int i, PVector [] pos){
  PVector v1=PVector.sub(pos[ b[i][0] ],pos[ b[i][1] ]);
  PVector v2=PVector.sub(pos[ b[i][2] ],pos[ b[i][3] ]);
  return PVector.angleBetween(v1,v2)-angle0;
}
//float Cbend(PVector[] pos){//acos() in the future
//  PVector v1=PVector.sub(pos[1],pos[0]);
//  PVector v2=PVector.sub(pos[2],pos[1]);
//  return PVector.angleBetween(v1,v2)-angle0;
//}
//float Canother(int Cj){
//  return Ci(Cj, pos);
//}
float C(int Cj){
  if(Cj<N-1) return Ci(Cj,pos);    
  //if(Cj==0) return Ci(0,pos);//C1(pos);
  //if(Cj==1) return Ci(1,pos);//C2(pos);
  //if(Cj==2) return Ci(2,pos);
  //if(Cj==3) return Ci(3,pos);
  
  else return Cbendi(Cj-(N-1), pos);
  //if(Cj==4) return Cbendi(0,pos);//Cbend(pos);
  //if(Cj==5) return Cbendi(1,pos);
  //if(Cj==6) return Cbendi(2,pos);
  //return 0;
}
void calcGradient(int Cj, int Xi){//input:第幾個constraint, 第幾個點
  float d=0.001;//for gradient distance//未來:需要依需求,讓d變得更小,才可讓gradient sum為0的問題不出現
  float f1, f0;
  pos[Xi].x+=d;
  f1=C(Cj);
  pos[Xi].x-=d*2;
  f0=C(Cj);
  pos[Xi].x+=d;
  gradient[Xi].x=(f1-f0)/2/d;

  pos[Xi].y+=d;
  f1=C(Cj);
  pos[Xi].y-=d*2;
  f0=C(Cj);
  pos[Xi].y+=d;
  gradient[Xi].y=(f1-f0)/2/d;

  pos[Xi].z+=d;
  f1=C(Cj);
  pos[Xi].z-=d*2;
  f0=C(Cj);
  pos[Xi].z+=d;
  gradient[Xi].z=(f1-f0)/2/d;
}
void solver(){//Input: pos*3
  float maxMag=0;
  float []w=new float[N];//{0.2,0.2,0.2,0.2,0.2};//0.33333, 0.33333, 0.33333};
  for(int i=0;i<N;i++) w[i]=1.0/N;
  for(int Cj=0; Cj<(N-1)+(N-2); Cj++){//for(int Cj=0; Cj<7; Cj++){//7: N=5, (5-1)+(5-2)=>7
    //partial gradient C[?]
    for(int Xi=1;Xi<N;Xi++){
      calcGradient(Cj, Xi);
    }
    float gradientSum=0;
    for(int Xi=1;Xi<N;Xi++){
      gradientSum += w[Xi]*gradient[Xi].magSq();
    }
    if(gradientSum<0.0000001){
      println("gradient sum very small");
      continue;
    }
    float lambda = C(Cj)/gradientSum;
    for(int Xi=1;Xi<N;Xi++){  //更新
      PVector diff=PVector.mult(gradient[Xi], -lambda*w[Xi]);
      pos[Xi].add(diff);
      if(diff.mag()>maxMag) maxMag=diff.mag();
    }
  }
  if(maxMag<0.1) bSolving=false;//距離夠小,就停止計算
}
void draw(){
  PVector g=new PVector(0, 0.98);//還沒有乘上 delta T 及重量
  //printNAN();
  if(bSolving){
    for(int i=1; i<N; i++){
      v[i].add(g);//step (5) 還沒有乘上 delta T 及重量
      //step (6) damping 還沒有做
      pos[i].x = pos0[i].x + v[i].x; //step (7)
      pos[i].y = pos0[i].y + v[i].y;
    }
    //step (8) collision constration 還沒有做 
    solver();//step (9)-(11)

    for(int i=1; i<N; i++){
      v[i].x = pos[i].x - pos0[i].x;//step (13)
      v[i].y = pos[i].y - pos0[i].y;
      pos0[i].x = pos[i].x;//step (14)
      pos0[i].y = pos[i].y;
    }
    //step (16) 是碰撞時的 friction 及 恢復係數
  }
  background(128);
  for(int i=0;i<N-1;i++) myLine(pos[i], pos[i+1]);
  for(int i=0;i<N;i++){
    if(i==N-1) fill(255,0,0);
    else fill(255);
    ellipse(pos[i].x, pos[i].y, 20,20);
  }
}
void mousePressed(){
  bSolving=true;
}
void keyPressed(){
  if(key=='c' || key=='C'){//把跑掉的東西,放回中心點
    PVector c=new PVector();
    PVector c2=new PVector(width/2,height/2);
    for(int i=0;i<N;i++){
      c.add(pos[i]);
    }
    c.div(N);
    for(int i=0;i<N;i++){
      pos[i].sub(c).add(c2);
    }
  
}}


6.移動長方形,使其旋轉的中心點移至長方形的末端

#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //
    glPushMatrix();
        glRotatef(ang,0,0,1);
        glTranslatef(0.25,0,0);//移動物體
        glScalef(0.5,0.1,0.1);
        glColor3f(1,0,1);
        glutSolidCube(1);
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}

7.移動長方形,使其在正方形其中一角做旋轉


#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
void hand(){
glPushMatrix();
        glScalef(0.5,0.1,0.1);
        glColor3f(1,0,0);
        glutSolidCube(1);
glPopMatrix();
}
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1,1,1);
    glutSolidCube(1);
    glPushMatrix();
        glTranslatef(0.5,0.5,0);
        glRotatef(ang,0,0,1);
        glTranslatef(0.25,0,0);
        hand();
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}

8.接續第7題,再新增一個長方形,在正方形其中一角2個長方形相連做手臂旋轉


#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
void hand(){
glPushMatrix();
        glScalef(0.5,0.1,0.1);
        glColor3f(1,0,0);
        glutSolidCube(1);
glPopMatrix();
}
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1,1,1);
    glutSolidCube(0.5);
    glPushMatrix();
        glTranslatef(0.25,0.25,0);
        glRotatef(ang,0,0,1);
        glTranslatef(0.25,0,0);
        hand();
        glPushMatrix();
            glTranslatef(0.25,0,0);
            glRotatef(ang,0,0,1);
            glTranslatef(0.25,0,0);
            hand();

        glPopMatrix();
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}
9.接續第8題,在左邊再加一個一樣的手臂
#include <GL/glut.h>
#include<math.h>
#include<stdio.h>
float ang=0;
int n=0,vx[9999],vy[9999];
void hand(){
glPushMatrix();
        glScalef(0.5,0.1,0.1);
        glColor3f(1,0,0);
        glutSolidCube(1);
glPopMatrix();
}
static void display()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1,1,1);
    glutSolidCube(0.5);
    glPushMatrix();
        glTranslatef(0.25,0.25,0);
        glRotatef(ang,0,0,1);
        glTranslatef(0.25,0,0);
        hand();
        glPushMatrix();
            glTranslatef(0.25,0,0);
            glRotatef(ang,0,0,1);
            glTranslatef(0.25,0,0);
            hand();
        glPopMatrix();

    glPopMatrix();
        glPushMatrix();
        glTranslatef(-0.25,0.25,0);
        glRotatef(-ang,0,0,1);
        glTranslatef(-0.25,0,0);
        hand();
        glPushMatrix();
            glTranslatef(-0.25,0,0);
            glRotatef(-ang,0,0,1);
            glTranslatef(-0.25,0,0);
            hand();
        glPopMatrix();
    glPopMatrix();
    glutSwapBuffers();
    ang++;
}
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("GLUT Shapes");
    glutDisplayFunc(display);
    glutIdleFunc(display);
    glutMainLoop();
}




沒有留言:

張貼留言

距地表面160 Week11

 #include "glm.h" GLMmodel* pmodel = NULL; void drawmodel(void) {     if (!pmodel) { pmodel = glmReadOBJ("data/porsche.obj...