球面線形補間

「球面線形補間」の編集履歴(バックアップ)一覧はこちら

球面線形補間」(2014/04/16 (水) 19:26:16) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

<p><strong>クォータニオンとクォータニオンを補間するには<br /> 『球面線形補間』を使います。</strong></p> <p><img alt="" src="http://www21.atwiki.jp/opengl?cmd=upload&amp;act=open&amp;pageid=149&amp;file=lin.png" /></p> <table border="1" cellspacing="1" cellpadding="1" width="600"><tbody><tr><td> <p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #include &lt;GL/freeglut/freeglut.h&gt;<br /> #include &lt;stdio.h&gt;<br /> #include &lt;math.h&gt;</p> <p>#define WIDTH 320<br /> #define HEIGHT 240</p> <p>#define PAI 3.14159</p> <p>//黄色<br /> GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0};</p> <p>bool flag=true;<br /> float t=0.0f;</p> <p>struct Vector3f{<br />  float x;<br />  float y;<br />  float z;<br /> }vec3d;</p> <p>//クォータニオン構造体<br /> struct Quaternion{<br />  float w;<br />  float x;<br />  float y;<br />  float z;<br /> }qua;</p> <p>//マトリクス構造体<br /> struct MATRIX {<br />     union {<br />         struct {<br />             float _11, _12, _13, _14;<br />             float _21, _22, _23, _24;<br />             float _31, _32, _33, _34;<br />             float _41, _42, _43, _44;<br />         };<br />         float mat_4x4[4][4];<br />   float mat_16[16];<br />     };<br />  MATRIX(){//単位行列に初期化<br />   for(int i=0;i&lt;16;i++){<br />    this-&gt;mat_16[i]=0;<br />   }<br />   this-&gt;_11=this-&gt;_22=this-&gt;_33=this-&gt;_44=1;<br />  }<br />  void PRINT(char* text){<br />   printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />    text,<br />    this-&gt;_11,this-&gt;_21,this-&gt;_31,this-&gt;_41,<br />    this-&gt;_12,this-&gt;_22,this-&gt;_32,this-&gt;_42,<br />    this-&gt;_13,this-&gt;_23,this-&gt;_33,this-&gt;_43,<br />    this-&gt;_14,this-&gt;_24,this-&gt;_34,this-&gt;_44);<br />  }<br /> };</p> <p><br /> //任意軸回転をクォータニオンにする<br /> Quaternion RotateToQuaternion(Vector3f vAxis,float Angle)<br /> {<br />  Quaternion q;<br />     float radian = (float)(Angle * (PAI / 180.0) / 2.0);<br />     float s = sin(radian);<br />  q.w=cos(radian);<br />  q.x=vAxis.x*s;<br />  q.y=vAxis.y*s;<br />  q.z=vAxis.z*s;<br />  return q;<br /> }</p> <p>//クォータニオンを回転行列にする<br /> MATRIX QuaternionToMatrix(Quaternion q){<br />  MATRIX ret;<br />     float sx = q.x * q.x;<br />     float sy = q.y * q.y;<br />     float sz = q.z * q.z;<br />     float cx = q.y * q.z;<br />     float cy = q.x * q.z;<br />     float cz = q.x * q.y;<br />     float wx = q.w * q.x;<br />     float wy = q.w * q.y;<br />     float wz = q.w * q.z;</p> <p> ret._11= 1.0f - 2.0f * (sy + sz);<br />  ret._12= 2.0f * (cz + wz);<br />  ret._13= 2.0f * (cy - wy);<br />  ret._21= 2.0f * (cz - wz);<br />  ret._22= 1.0f - 2.0f * (sx + sz);<br />  ret._23= 2.0f * (cx + wx);<br />  ret._31= 2.0f * (cy + wy);<br />  ret._32= 2.0f * (cx - wx);<br />  ret._33= 1.0f - 2.0f * (sx + sy);<br />  ret._41= 0.0f;<br />  ret._42= 0.0f;<br />  ret._43= 0.0f;<br />  return ret;<br /> }</p> <p>//回転行列をクォータニオンにする<br /> Quaternion MatrixToQuaternion(MATRIX mat){<br />  Quaternion q;</p> <p>    float s;<br />     float tr = mat._11 + mat._22 + mat._33 + 1.0f;<br />     if (tr &gt;= 1.0f) {<br />         s = 0.5f / sqrt(tr);<br />   q.w= 0.25f / s;<br />   q.x= (mat._23 - mat._32) * s;<br />         q.y= (mat._31 - mat._13) * s;<br />   q.z= (mat._12 - mat._21) * s;<br />   return q;<br />     }else{<br />         float max;<br />   if(mat._22 &gt; mat._33){<br />    max = mat._22;<br />   }else{<br />    max = mat._33;<br />   }<br />        <br />         if (max &lt; mat._11) {<br />             s = sqrt(mat._11 - (mat._22 + mat._33) + 1.0f);<br />             float x = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= x;<br />    q.y= (mat._12 + mat._21) * s;<br />    q.z= (mat._31 + mat._13) * s;<br />    q.w= (mat._23 - mat._32) * s;<br />             return q;<br />         }else if (max == mat._22) {<br />             s = sqrt(mat._22 - (mat._33 + mat._11) + 1.0f);<br />             float y = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= (mat._12 + mat._21) * s;<br />             q.y= y;<br />    q.z= (mat._23 + mat._32) * s;<br />    q.w= (mat._31 - mat._13) * s;<br />             return q;<br />         }else{<br />             s = sqrt(mat._33 - (mat._11 + mat._22) + 1.0f);<br />             float z = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= (mat._31 + mat._13) * s;<br />    q.y= (mat._23 + mat._32) * s;<br />             q.z= z;<br />    q.w= (mat._12 - mat._21) * s;<br />             return q;<br />         }<br />     }<br /> }</p> <p>//球面線形補間<br /> Quaternion Spherical_Linear_Interpolation( Quaternion q1, Quaternion q2, float t)<br /> {<br />   Quaternion q;<br />   float qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;<br />   float ss = 1.0f - qr * qr;<br />  <br />   if (ss == 0.0f) {<br />    q.w = q1.w;<br />    q.x = q1.x;<br />    q.y = q1.y;<br />    q.z = q1.z;<br />    return q;<br />   }<br />   else {<br />     float sp = sqrt(ss);<br />     float ph = acos(qr);<br />     float pt = ph * t;<br />     float t1 = sin(pt) / sp;<br />     float t0 = sin(ph - pt) / sp;<br />    <br />  q.w = q1.w * t0 + q2.w * t1;<br />  q.x = q1.x * t0 + q2.x * t1;<br />  q.y = q1.y * t0 + q2.y * t1;<br />  q.z = q1.z * t0 + q2.z * t1;<br />  return q;<br />   }<br /> }</p> <p><br /> MATRIX model;</p> <p>void display(void)<br /> {<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  glViewport(0, 0, WIDTH, HEIGHT);<br />  glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  //視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />  gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);<br />  glMatrixMode(GL_MODELVIEW);</p> <p> glLoadIdentity();</p> <p> glRotatef(36.8f,1.0f,0.0f,0.0f);<br />  glGetFloatv(GL_MODELVIEW_MATRIX,&amp;model.mat_16[0]);<br />  Quaternion q1=MatrixToQuaternion(model);</p> <p> glLoadIdentity();</p> <p> glRotatef(240.4f,0.0f,1.0f,0.0f);<br />  glGetFloatv(GL_MODELVIEW_MATRIX,&amp;model.mat_16[0]);<br />  Quaternion q2=MatrixToQuaternion(model);</p> <p> Quaternion q3=Spherical_Linear_Interpolation(q1,q2,t);<br />  MATRIX mat=QuaternionToMatrix(q3);</p> <p> glLoadIdentity();<br />   gluLookAt(0.0,500.0,500.0,<br />       0.0,0.0,0.0,<br />      0.0,1.0,0.0);</p> <p> glMultMatrixf(&amp;mat.mat_16[0]);<br />  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);<br />  glutSolidCube(150.0);</p> <p> glutSwapBuffers();<br /> }<br /> void idle(void)<br /> {<br />  glutPostRedisplay();<br /> }<br /> void Init(){<br />  glClearColor(0.3f, 0.3f, 0.3f, 1.0f);<br />  glEnable(GL_DEPTH_TEST);<br />  glEnable(GL_LIGHTING);<br />  glEnable(GL_LIGHT0);<br /> }</p> <p>void timer(int value) {<br />  if(t&gt;1.0f)flag=false;<br />  if(t&lt;0.0f)flag=true;<br />  if(flag){t+=0.01f;}else{t-=0.01f;}<br />  glutTimerFunc(10 , timer , 0);<br /> }</p> <p>int main(int argc, char *argv[])<br /> {<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutCreateWindow("球面線形補間");<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  glutTimerFunc(10 , timer , 0);<br />  Init();<br />  glutMainLoop();<br />  return 0;<br /> }</p> </td> </tr></tbody></table><p> </p> <p> </p> <p> </p>
<p><strong>クォータニオンとクォータニオンを補間するには<br /> 『球面線形補間』を使います。</strong></p> <p><img alt="" src="http://cdn21.atwikiimg.com/opengl?cmd=upload&amp;act=open&amp;pageid=149&amp;file=lin.png" /></p> <table border="1" cellpadding="1" cellspacing="1" width="600"><tbody><tr><td> <p>#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")<br /> #include &lt;GL/freeglut/freeglut.h&gt;<br /> #include &lt;stdio.h&gt;<br /> #include &lt;math.h&gt;</p> <p>#define WIDTH 320<br /> #define HEIGHT 240</p> <p>#define PAI 3.14159</p> <p>//黄色<br /> GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0};</p> <p>bool flag=true;<br /> float t=0.0f;</p> <p>struct Vector3f{<br />  float x;<br />  float y;<br />  float z;<br /> }vec3d;</p> <p>//クォータニオン構造体<br /> struct Quaternion{<br />  float w;<br />  float x;<br />  float y;<br />  float z;<br /> }qua;</p> <p>//マトリクス構造体<br /> struct MATRIX {<br />     union {<br />         struct {<br />             float _11, _12, _13, _14;<br />             float _21, _22, _23, _24;<br />             float _31, _32, _33, _34;<br />             float _41, _42, _43, _44;<br />         };<br />         float mat_4x4[4][4];<br />   float mat_16[16];<br />     };<br />  MATRIX(){//単位行列に初期化<br />   for(int i=0;i&lt;16;i++){<br />    this-&gt;mat_16[i]=0;<br />   }<br />   this-&gt;_11=this-&gt;_22=this-&gt;_33=this-&gt;_44=1;<br />  }<br />  void PRINT(char* text){<br />   printf("%s\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n%f,%f,%f,%f\n\n",<br />    text,<br />    this-&gt;_11,this-&gt;_21,this-&gt;_31,this-&gt;_41,<br />    this-&gt;_12,this-&gt;_22,this-&gt;_32,this-&gt;_42,<br />    this-&gt;_13,this-&gt;_23,this-&gt;_33,this-&gt;_43,<br />    this-&gt;_14,this-&gt;_24,this-&gt;_34,this-&gt;_44);<br />  }<br /> };</p> <p><br /> //任意軸回転をクォータニオンにする<br /> Quaternion RotateToQuaternion(Vector3f vAxis,float Angle)<br /> {<br />  Quaternion q;<br />     float radian = (float)(Angle * (PAI / 180.0) / 2.0);<br />     float s = sin(radian);<br />  q.w=cos(radian);<br />  q.x=vAxis.x*s;<br />  q.y=vAxis.y*s;<br />  q.z=vAxis.z*s;<br />  return q;<br /> }</p> <p>//クォータニオンを回転行列にする<br /> MATRIX QuaternionToMatrix(Quaternion q){<br />  MATRIX ret;<br />     float sx = q.x * q.x;<br />     float sy = q.y * q.y;<br />     float sz = q.z * q.z;<br />     float cx = q.y * q.z;<br />     float cy = q.x * q.z;<br />     float cz = q.x * q.y;<br />     float wx = q.w * q.x;<br />     float wy = q.w * q.y;<br />     float wz = q.w * q.z;</p> <p> ret._11= 1.0f - 2.0f * (sy + sz);<br />  ret._12= 2.0f * (cz + wz);<br />  ret._13= 2.0f * (cy - wy);<br />  ret._21= 2.0f * (cz - wz);<br />  ret._22= 1.0f - 2.0f * (sx + sz);<br />  ret._23= 2.0f * (cx + wx);<br />  ret._31= 2.0f * (cy + wy);<br />  ret._32= 2.0f * (cx - wx);<br />  ret._33= 1.0f - 2.0f * (sx + sy);<br />  ret._41= 0.0f;<br />  ret._42= 0.0f;<br />  ret._43= 0.0f;<br />  return ret;<br /> }</p> <p>//回転行列をクォータニオンにする<br /> Quaternion MatrixToQuaternion(MATRIX mat){<br />  Quaternion q;</p> <p>    float s;<br />     float tr = mat._11 + mat._22 + mat._33 + 1.0f;<br />     if (tr &gt;= 1.0f) {<br />         s = 0.5f / sqrt(tr);<br />   q.w= 0.25f / s;<br />   q.x= (mat._23 - mat._32) * s;<br />         q.y= (mat._31 - mat._13) * s;<br />   q.z= (mat._12 - mat._21) * s;<br />   return q;<br />     }else{<br />         float max;<br />   if(mat._22 &gt; mat._33){<br />    max = mat._22;<br />   }else{<br />    max = mat._33;<br />   }<br />        <br />         if (max &lt; mat._11) {<br />             s = sqrt(mat._11 - (mat._22 + mat._33) + 1.0f);<br />             float x = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= x;<br />    q.y= (mat._12 + mat._21) * s;<br />    q.z= (mat._31 + mat._13) * s;<br />    q.w= (mat._23 - mat._32) * s;<br />             return q;<br />         }else if (max == mat._22) {<br />             s = sqrt(mat._22 - (mat._33 + mat._11) + 1.0f);<br />             float y = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= (mat._12 + mat._21) * s;<br />             q.y= y;<br />    q.z= (mat._23 + mat._32) * s;<br />    q.w= (mat._31 - mat._13) * s;<br />             return q;<br />         }else{<br />             s = sqrt(mat._33 - (mat._11 + mat._22) + 1.0f);<br />             float z = s * 0.5f;<br />             s = 0.5f / s;<br />    q.x= (mat._31 + mat._13) * s;<br />    q.y= (mat._23 + mat._32) * s;<br />             q.z= z;<br />    q.w= (mat._12 - mat._21) * s;<br />             return q;<br />         }<br />     }<br /> }</p> <p>//球面線形補間<br /> Quaternion Spherical_Linear_Interpolation( Quaternion q1, Quaternion q2, float t)<br /> {<br />   Quaternion q;<br />   float qr = q1.w * q2.w + q1.x * q2.x + q1.y * q2.y + q1.z * q2.z;<br />   float ss = 1.0f - qr * qr;<br />  <br />   if (ss == 0.0f) {<br />    q.w = q1.w;<br />    q.x = q1.x;<br />    q.y = q1.y;<br />    q.z = q1.z;<br />    return q;<br />   }<br />   else {<br />     float sp = sqrt(ss);<br />     float ph = acos(qr);<br />     float pt = ph * t;<br />     float t1 = sin(pt) / sp;<br />     float t0 = sin(ph - pt) / sp;<br />    <br />  q.w = q1.w * t0 + q2.w * t1;<br />  q.x = q1.x * t0 + q2.x * t1;<br />  q.y = q1.y * t0 + q2.y * t1;<br />  q.z = q1.z * t0 + q2.z * t1;<br />  return q;<br />   }<br /> }</p> <p><br /> MATRIX model;</p> <p>void display(void)<br /> {<br />  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);<br />  glViewport(0, 0, WIDTH, HEIGHT);<br />  glMatrixMode(GL_PROJECTION);<br />  glLoadIdentity();<br />  //視野角,アスペクト比(ウィンドウの幅/高さ),描画する範囲(最も近い距離,最も遠い距離)<br />  gluPerspective(30.0, (double)WIDTH / (double)HEIGHT, 1.0, 1000.0);<br />  glMatrixMode(GL_MODELVIEW);</p> <p> glLoadIdentity();</p> <p> glRotatef(36.8f,1.0f,0.0f,0.0f);<br />  glGetFloatv(GL_MODELVIEW_MATRIX,&amp;model.mat_16[0]);<br />  Quaternion q1=MatrixToQuaternion(model);</p> <p> glLoadIdentity();</p> <p> glRotatef(240.4f,0.0f,1.0f,0.0f);<br />  glGetFloatv(GL_MODELVIEW_MATRIX,&amp;model.mat_16[0]);<br />  Quaternion q2=MatrixToQuaternion(model);</p> <p> Quaternion q3=Spherical_Linear_Interpolation(q1,q2,t);<br />  MATRIX mat=QuaternionToMatrix(q3);</p> <p> glLoadIdentity();<br />   gluLookAt(0.0,500.0,500.0,<br />       0.0,0.0,0.0,<br />      0.0,1.0,0.0);</p> <p> glMultMatrixf(&amp;mat.mat_16[0]);<br />  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);<br />  glutSolidCube(150.0);</p> <p> glutSwapBuffers();<br /> }<br /> void idle(void)<br /> {<br />  glutPostRedisplay();<br /> }<br /> void Init(){<br />  glClearColor(0.3f, 0.3f, 0.3f, 1.0f);<br />  glEnable(GL_DEPTH_TEST);<br />  glEnable(GL_LIGHTING);<br />  glEnable(GL_LIGHT0);<br /> }</p> <p>void timer(int value) {<br />  if(t&gt;1.0f)flag=false;<br />  if(t&lt;0.0f)flag=true;<br />  if(flag){t+=0.01f;}else{t-=0.01f;}<br />  glutTimerFunc(10 , timer , 0);<br /> }</p> <p>int main(int argc, char *argv[])<br /> {<br />  glutInitWindowPosition(100, 100);<br />  glutInitWindowSize(WIDTH, HEIGHT);<br />  glutInit(&amp;argc, argv);<br />  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);<br />  glutCreateWindow("球面線形補間");<br />  glutDisplayFunc(display);<br />  glutIdleFunc(idle);<br />  glutTimerFunc(10 , timer , 0);<br />  Init();<br />  glutMainLoop();<br />  return 0;<br /> }</p> </td> </tr></tbody></table><p> </p> <p> </p> <p> </p>

表示オプション

横に並べて表示:
変化行の前後のみ表示: