- 內插 (Excel學習內插)
2. time(介於0-1之間) alpha(介於0-1之間) angle(舊的角度/新的角度)
3. 內插公式 alpha*新的角度+(1-alpha)*舊的角度
- 內插 (程式實作)
3-1 擺完動作後按s,之後按 r 在一直按 p 就可以播放動畫
#include <GL/glut.h>
#include <stdio.h> ///為了 printf , fprintf, fopen, fclose
float angle[20], oldX=0; ///角度歸零
int angleID=0; ///0為第0個關節...以此類推
FILE * fout = NULL, * fin = NULL;
void myWrite(){
if(fout==NULL) fout= fopen("file.txt", "w+");
for(int i=0; i<20; i++){
printf("%.2f ", angle[i]);
fprintf(fout, "%.2f ", angle[i]);
}
printf("\n");
fprintf(fout, "\n");
///少了fclose,因為不想印一行就結束,要多行一點
}
float OldAngle[20], NewAngle[20];
void myRead()
{
if(fout!=NULL){fclose(fout); fout=NULL;}
if(fin==NULL) fin= fopen("file.txt", "r");
for(int i=0; i<20; i++){
OldAngle[i] = NewAngle[i];
fscanf(fin, "%f", &NewAngle[i]);
///fscanf(fin, "%f", &angle[i]);
}
glutPostRedisplay(); ///重畫畫面
}
void myInterpolate(float alpha){
for(int i=0; i<20; i++){
angle[i]= alpha* NewAngle[i]+ (1-alpha)* OldAngle[i];
printf("%.2f ", angle[i]);
}
printf("\n");
glutPostRedisplay(); ///重畫畫面
}
float alpha= 0;
void keyboard(unsigned char key, int x, int y)
{
if(key == '0') angleID=0; ///預設
if(key == '1') angleID=1;
if(key == '2') angleID=2;
if(key == '3') angleID=3;
if(key == 'r') myRead();
if(key == 's') myWrite(); ///save
if(key == 'p') {
myInterpolate(alpha);///內插
alpha = (alpha+0.1);
if(alpha>1) alpha= alpha-1;
}
}
void mouse(int button, int state, int x, int y)
{
oldX= x;
}
void motion(int x, int y)
{
angle[angleID] += (x-oldX);
///myWrite(); ///沒必要一直寫檔
oldX= x;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1, 1, 1); ///白色的
glRectf(0.3, 0.5, -0.3, -0.2); ///身體
glPushMatrix(); ///右半邊
glTranslatef(0.3, 0.4, 0);
glRotatef(angle[0], 0, 0, 1);
glTranslatef(-0.3, -0.4, 0);
glColor3f(1, 0, 0); ///紅色
glRectf(0.3, 0.5, 0.8, 0.3); ///手臂
glPushMatrix();
glTranslatef(0.8, 0.4, 0);/// 3. 把手肘掛在關節上
glRotatef(angle[1], 0, 0, 1);/// 2. 旋轉
glTranslatef(-0.8, -0.4, 0);/// 1. 把手肘旋轉中心放到中間
glColor3f(0, 1, 0);
glRectf(0.8, 0.5, 1.1, 0.3);/// 再畫手肘
glPopMatrix();
glPopMatrix();
glPushMatrix(); ///左半邊
glTranslatef(-0.3, 0.4, 0);
glRotatef(angle[2], 0, 0, 1);
glTranslatef(0.3, -0.4, 0);
glColor3f(1, 0, 0); ///紅色
glRectf(-0.3, 0.5, -0.8, 0.3); ///手臂
glPushMatrix();
glTranslatef(-0.8, 0.4, 0);/// 3. 把手肘掛在關節上
glRotatef(angle[3], 0, 0, 1);/// 2. 旋轉
glTranslatef(0.8, -0.4, 0);/// 1. 把手肘旋轉中心放到中間
glColor3f(0, 1, 0);
glRectf(-0.8, 0.5, -1.1, 0.3);/// 再畫手肘
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc,char**argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Week15_angles_TRT_again");
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc(display); ///不放Idle
glutMainLoop();
}
4. 加入timer 讓他自動做內插,按p可以播放
4-1 先4個動作,存好後把程式關掉
4-2 利用glutTimerFunc(0, timer, 0) 來開始播放
4-3 在 keyboard-->if(key== 'p') 的地方 進行設定(play)
4-4 先myRead讀一行,再寫timer
4-5 timer中,由t先算出alpha
4-6 接著遇到有整除時,做新舊交換
4-7 丟進myInterpolate, 再做glutTimerFunc(33, timer, t+1);
4-8 其中的33為決定播放的時間
#include <GL/glut.h>
#include <stdio.h> ///為了 printf , fprintf, fopen, fclose
float angle[20], oldX=0; ///角度歸零
int angleID=0; ///0為第0個關節...以此類推
FILE * fout = NULL, * fin = NULL;
void myWrite(){
if(fout==NULL) fout= fopen("file.txt", "w+");
for(int i=0; i<20; i++){
printf("%.2f ", angle[i]);
fprintf(fout, "%.2f ", angle[i]);
}
printf("\n");
fprintf(fout, "\n");
///少了fclose,因為不想印一行就結束,要多行一點
}
float OldAngle[20], NewAngle[20];
void myRead()
{
if(fout!=NULL){fclose(fout); fout=NULL;}
if(fin==NULL) fin= fopen("file.txt", "r");
for(int i=0; i<20; i++){
OldAngle[i] = NewAngle[i];
fscanf(fin, "%f", &NewAngle[i]);
///fscanf(fin, "%f", &angle[i]);
}
glutPostRedisplay(); ///重畫畫面
}
void myInterpolate(float alpha){
for(int i=0; i<20; i++){
angle[i]= alpha* NewAngle[i]+ (1-alpha)* OldAngle[i];
printf("%.2f ", angle[i]);
}
printf("\n");
glutPostRedisplay(); ///重畫畫面
}
///float alpha= 0;
void timer(int t){
float alpha = (t%100)/100.0; ///算出alpha
if(t%100==0) myRead();///遇到30整除時,做新舊交接
myInterpolate(alpha);
glutTimerFunc(33, timer, t+1); ///33為決定播放的時間
}
void keyboard(unsigned char key, int x, int y)
{
if(key == '0') angleID=0; ///預設
if(key == '1') angleID=1;
if(key == '2') angleID=2;
if(key == '3') angleID=3;
if(key == 'r') myRead();
if(key == 's') myWrite(); ///save
if(key == 'p') {
myRead();///先讀一行
glutTimerFunc(0, timer, 0); ///馬上開始播放動畫
///myInterpolate(alpha);///內插
///alpha = (alpha+0.1);
///if(alpha>1) alpha= alpha-1;
}
}
void mouse(int button, int state, int x, int y)
{
oldX= x;
}
void motion(int x, int y)
{
angle[angleID] += (x-oldX);
///myWrite(); ///沒必要一直寫檔
oldX= x;
glutPostRedisplay();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1, 1, 1); ///白色的
glRectf(0.3, 0.5, -0.3, -0.2); ///身體
glPushMatrix(); ///右半邊
glTranslatef(0.3, 0.4, 0);
glRotatef(angle[0], 0, 0, 1);
glTranslatef(-0.3, -0.4, 0);
glColor3f(1, 0, 0); ///紅色
glRectf(0.3, 0.5, 0.8, 0.3); ///手臂
glPushMatrix();
glTranslatef(0.8, 0.4, 0);/// 3. 把手肘掛在關節上
glRotatef(angle[1], 0, 0, 1);/// 2. 旋轉
glTranslatef(-0.8, -0.4, 0);/// 1. 把手肘旋轉中心放到中間
glColor3f(0, 1, 0);
glRectf(0.8, 0.5, 1.1, 0.3);/// 再畫手肘
glPopMatrix();
glPopMatrix();
glPushMatrix(); ///左半邊
glTranslatef(-0.3, 0.4, 0);
glRotatef(angle[2], 0, 0, 1);
glTranslatef(0.3, -0.4, 0);
glColor3f(1, 0, 0); ///紅色
glRectf(-0.3, 0.5, -0.8, 0.3); ///手臂
glPushMatrix();
glTranslatef(-0.8, 0.4, 0);/// 3. 把手肘掛在關節上
glRotatef(angle[3], 0, 0, 1);/// 2. 旋轉
glTranslatef(0.8, -0.4, 0);/// 1. 把手肘旋轉中心放到中間
glColor3f(0, 1, 0);
glRectf(-0.8, 0.5, -1.1, 0.3);/// 再畫手肘
glPopMatrix();
glPopMatrix();
glutSwapBuffers();
}
int main(int argc,char**argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Week15_angles_TRT_again");
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
glutDisplayFunc(display); ///不放Idle
glutMainLoop();
}
- 相機(範例:https://jsyeh.org/3dcg10/)
2. 點擊 Projection 開始實作
3. eye 相機看你的位置(從哪裡看)
4. center 決定相機要看的中心位置
(由下面圖片來說 是以人的左手當作中心,圍繞著手拍)
5. up 為相機旋轉位置
- 相機(程式實作)
static void resize(int width, int height)
{ ///aspect ratio 長寬比
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION); ///投影-把3D投成2D畫面
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0);
glMatrixMode(GL_MODELVIEW); ///3D經過轉換到最後的相機
glLoadIdentity() ;
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutSolidTeapot(2); ///大茶壺
glutSwapBuffers();
}
void motion(int x, int y)
{
glMatrixMode(GL_MODELVIEW); ///3D經過轉換到最後的相機
glLoadIdentity();
gluLookAt((x-150)/15.0, (y-150)/15.0, 3, ///eye
0, 0, 0, ///center
0, 1, 0); ///up
glutPostRedisplay();
}
void reshape(int w, int h)
{
const float ar = (float) w / (float) h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION); ///投影-把3D投成2D畫面
glLoadIdentity();
gluPerspective(60, ar, 0.1, 100);
glMatrixMode(GL_MODELVIEW); ///3D經過轉換到最後的相機
glLoadIdentity() ;
gluLookAt(0, 0, 3,
0, 0, 0,
0, 1, 0);
}
int main(int argc,char**argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Week16_lookat");
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMotionFunc(motion);
glutMainLoop();
}












沒有留言:
張貼留言