質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

4×4の行列を算出したい

解決済

回答 9

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,721

txty

score -12

再追記修正 調べたら http://www.opengl-tutorial.org/jp/beginners-tutorials/tutorial-3-matrices/ こういうことだった。
float型だと手計算と一致せず、double型だと手計算と一致したのでdouble型にしました。
でも、三回目の計算がまったくあたらないので注意です。

後、計算が遅いです。

でも、平行移動のベクトルは
1 0 0 Tx       x    x+Tx*0    x
0 1 0 Ty       y       y+Ty*0    y
0 0 1 Tz   *   z  = z+Tz*0  = z
0 0 0 1        0       0         0    ベクトルのままではないのか (引用 ゲームを動かす技術と発想R )  
数値は、なんでも言いわけではなさそうだった。で、現状方程式で解いてる。(3Dグラフィックスのための数学では普通に4*4の計算をしている。)

double a[16]={
1.000000,0.000000,0.000000,0.000000,
0.000000,1.000000,0.000000,0.000000,
0.000000,0.000000,1.000000,0.000000,
0.000000,0.000000,0.000000,1.000000};


double b[16]={
1.000000,0.000000,0.000000,0.000000,
0.000000,1.000000,0.000000,0.000000,
0.000000,0.000000,1.000000,0.000000,
0.000000,0.000000,0.000000,1.000000};

で数値は何でもいいとして
a×bの 4×4の行列(間違えたら嫌なので強調)を算出する簡単な方法がありましたら、教えてください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2020/08/09 11:36

    はずさないことで、この質問を見た人からあなたへの対応が親切でなくなることはあると思いますが、それもどうだかわからないと言うなら好きにすればいいと思います。ただ、それなら回答は期待しないことです。一人でどうぞ。

    あまりしつこく無意味な通知を送ってくるなら、暑くてイライラしがちな季節なので、送られた人の態度もあまり良くない方向へと変化するかもしれませんね。

    キャンセル

  • txty

    2020/08/09 11:41

    はい、あとはひとりでって方向にします。もう当初、欲しかったものは手に入ったので静かにしてます。

    キャンセル

  • 退会済みユーザー

    2020/08/09 14:33

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 9

+2

Frame_Scene_Root[0]とFrame_body[0]がfloat型にできなかったんだが、元の値が変わってしまうのですがどうすべきでしょうか。

なに言ってるかわからん。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/04 09:41

    疑問に思ってました。返信で const float* 型について確信がもてました。今度から使います

    キャンセル

  • 2020/07/04 09:45

    void Ranks( float *temp , const float* a, const float *b) { a[0] = 0; }
    をコンパイルしてみるといい。エラー吐いてくれるから。

    キャンセル

  • 2020/07/04 09:58 編集

    main.cc: 関数 ‘void Ranks(float*, const float*, const float*)’ 内:
    /main.cc:40:7: エラー: 読み取り専用位置 ‘* a’ への代入です
    a[0]=0;
    ^
    確かにエラーです。明示てきでした。

    キャンセル

+1

評価する人は自前に 4*4のコードを作成し書き込んでいけっていったんだから、書き込んでいけよ。

<?php
$intA = [
3, 4, 5, 5,
6, 3, 4, 3,
3, 4, 5, 7,
9, 2, 3, 4
];

$intB = [
3, 4, 5, 5,
6, 3, 4, 3,
3, 4, 5, 7,
9, 2, 3, 4
];

$result = [];

for( $i = 0; $i < 16; $i++ ){
  $result[] = $intA[$i] * $intB[$i];
} 

for( $i = 0; $i < 4; $i++ ){
  for( $j = 0; $j < 4; $j++ ){
    echo $result[ ($i * 4) + $j ], ' ';
  }
  echo '<br />';
}

もうすぐ定期試験2科目始まるのでレスは遅れますが悪しからず。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/19 16:15

    double型にしました。

    キャンセル

+1

a×bの 4×4の行列(間違えたら嫌なので強調)を算出する簡単な方法がありましたら

何らかのライブラリを使う,という方法.(マジレス)

一体何のために行列計算しているのかわからないけれども,その行列を使う目的によっては何らかのライブラリを導入している可能性があり,そうであって且つそこに行列を扱う機能が提供されているならばそれを使うのが手っ取り早い.

OpenCVとかEigenなら,行列用の型にoperator *が提供されているから,
A * Bとか書けばそれで済む.
OpenGLにはglMultMatrixなんてのがあるみたい(掛ける方向とか行列データの並び順とかの面が若干面倒そうかもだが).

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/19 16:14

    double型にしました。

    キャンセル

checkベストアンサー

0

簡単もなにもベクトルの内積を4x4回繰り返す以外なんかあるん?

[追記] 愚直な実装でよければ:

#include <stdio.h>

#define at(t,y,x) t[y*4+x]

int main() {
  float a[16] = {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,1.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000 };

  float b[16] = {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,1.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000 };

  float c[16];

  int row, col;
  for ( row = 0; row < 4; ++row ) {
    for ( col =0; col < 4; ++col ) {
      float sum = 0.0f;
      int t;
      for ( t = 0; t <4; ++t ) {
        sum += at(a,row,t) * at(b,t,col);
      }
      at(c,row,col) = sum;
    }
  }

  // できたかな?
  for ( row = 0; row < 4; ++row) {
    for ( col = 0; col < 4; ++col) {
      printf("%f ", at(c,row,col));
    }
    puts("");
  }
  return 0;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/03 21:00

    要は関数の中身をつくるのがめんどくさかっただけで、もう私のSAN値が足りないということです。

    キャンセル

  • 2020/07/03 21:10

    丸投げ了解。追記した。

    キャンセル

  • 2020/07/03 21:26

    凄いな。どうも。

    キャンセル

0

[別解] 関数 multiplies に仕立ててみた

#include <stdio.h>

#define at(t,y,x) t[y*4+x]

void multiplies(float* c, const float* a, const float* b) {
  int row, col;
  for ( row = 0; row < 4; ++row ) {
    for ( col =0; col < 4; ++col ) {
      float sum = 0.0f;
      int t;
      for ( t = 0; t <4; ++t ) {
        sum += at(a,row,t) * at(b,t,col);
      }
      at(c,row,col) = sum;
    }
  }
}

int main() {
  float a[16] = {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,1.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000 };

  float b[16] = {
    1.000000,0.000000,0.000000,0.000000,
    0.000000,1.000000,0.000000,0.000000,
    0.000000,0.000000,1.000000,0.000000,
    0.000000,0.000000,0.000000,1.000000 };

  float c[16];

  int row, col;

  multiplies(c, a, b);

  // できたかな?
  for ( row = 0; row < 4; ++row) {
    for ( col = 0; col < 4; ++col) {
      printf("%f ", at(c,row,col));
    }
    puts("");
  }
  return 0;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/04 19:28 編集

    1.サンプルが読めるレベルじゃない2.サンプルが読めないから、元の行列に影響があるか影響がないのために作成してくれたのか推し量れない3.元のプログラムにconst float*型で誤解が生じるのを防ぐために投稿した。誤解で苦しむのが嫌い。4.余力は、どうやったら頂点に影響を与えるのかを知りたい5.自分の態度が悪いのは自覚しているが厚本はもっとひどい。ってところです。はい。あとはテンションがhighだった。

    キャンセル

  • 2020/07/04 20:28

    > 何でこれが、元の行列に影響しないことになるんですか。
    1. 関数 multipliesでは元の行列a,bを書き換えていない(書き換えたらエラーとなるんだから)
    2. 関数 multiplies以外の部分でa,bを書き換えている個所が存在しない。

    キャンセル

  • 2020/07/04 23:45

    ちょっと理解が進まないので、既読したということだけ書いときます。

    キャンセル

0

解決したんじゃなかったんか?

a[4][4] と b[4][4] の積を c[4][4] に求める: 

#include <stdio.h>

void multiplies(float c[4][4], const float a[4][4], const float b[4][4]) {
  int row, col;
  for ( row = 0; row < 4; ++row ) {
    for ( col =0; col < 4; ++col ) {
      float sum = 0.0f;
      int t;
      for ( t = 0; t <4; ++t ) {
        sum += a[row][t] * b[t][col];
      }
      c[row][col] = sum;
    }
  }
}

int main() {
  float a[4][4] = {
    { 1.000000,0.000000,0.000000,0.000000 },
    { 0.000000,1.000000,0.000000,0.000000 },
    { 0.000000,0.000000,1.000000,0.000000 },
    { 0.000000,0.000000,0.000000,1.000000 },
  };

  float b[4][4] = {
    { 1.000000,0.000000,0.000000,0.000000 },
    { 0.000000,1.000000,0.000000,0.000000 },
    { 0.000000,0.000000,1.000000,0.000000 },
    { 0.000000,0.000000,0.000000,1.000000 },
  };

  float c[4][4];

  int row, col;

  multiplies(c, a, b);

  // できたかな?
  for ( row = 0; row < 4; ++row) {
    for ( col = 0; col < 4; ++col) {
      printf("%f ", c[row][col]);
    }
    puts("");
  }
  return 0;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/20 19:12 編集

    >ポインタを介することで書き換えることができるという意図がわからないので説明してほしいんですが、そろそろ終わりにしたいですよね
    multiplies(&Keka[0],&Bip01_R_UpperArm_FrameTransformMatrix[0],&Keka[0]);では電卓とずれるのに、double f[16];
    multiplies(&Keka[0],&Bip01_R_UpperArm_FrameTransformMatrix[0],&f[0]);ではいいの
    もちょっと分からないんですけど、自分は今度から &Keka[0]のかわりに &f[0]とか違う変数を結果に、わかるときまで、挟むことにしました。

    キャンセル

  • 2020/09/21 00:38 編集

    > ポインタを介することで書き換えることができるという意図がわからない
    void multiplies(int c, int a, int b) { c = a * b; } // a*bをcに求める

    これじゃダメ(ポインタを介さないとダメ)なことがわからないなら、教本を読んでください。

    > そろそろ終わりにしたいですよね

    同意します。

    キャンセル

  • 2020/09/21 08:18 編集

    void multiplies(int c, int a, int b){c= a*b;}それは引数が書き変わらないことはわかるけど、multiplies(&Keka[0],&Bip01_R_UpperArm_FrameTransformMatrix[0],&Keka[0]);も最後の&keka[0]以外さわってないので、書き変わるのはそこだけじゃないのでしょうか。はじめの&keka[0]と&Bip01_R_UpperArm_FrameTransformMatrix[0]は使用しているが触っていない。c++でいうmultiplies(int a,int b, int c)const メンバーがa, bで引数じゃない気がするが。みたいなものかと(int cはいじっていますが)。最後の&Keka[0]だけ変わることを期待します。
    じゃあそろそろ終わりということで。

    キャンセル

-5

引数で使った &Frame_Scene_Root[0],&Frame_body[0]が、逆だったかもしれません。逆の可能性が高いという感じです。
あと関数を何回も計算するのに、引数にconst を使うのは再利用の関点から、有り得ないことに気がつきました。自分が言いだしっぺです。すいません。

問題はここか。右から計算?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/05 07:16

    ?そもそも論としてconst_castなりなんなりすれば、const外せますが・・・constというのは、変更しないでほしいというAPI作者などからの意志伝達であり命令とは言い切れないのですが・・・

    キャンセル

  • 2020/08/05 07:21

    すみません。回答の前提についてです。4x4行列ということで1次元の4要素を持つベクター同士の乗算と受け取られる人がいるかも知れませんが、2次元の4要素の16の要素からなる行列同士の演算で数学でいう高校から大学で習う乗算演算を基本として回答しています。現在C++11がC++2Aになっているという時代背景を受けて、パラレル演算STLを背景に、GPGPUなどを平行に考えた場合、、前から掛けるか、後ろから掛けるか、つまり掛ける数かかけられる数かというところが焦点になると考えますが、それをもっとも端的なC++で表現せよといわれると、前const後ろconstと似たように 書き方によって意味が違うというネタ回答を含めつつ、真面目回答でも同じに近くなるように配慮して書いたつもりですが、未熟ですみません

    キャンセル

  • 2020/08/05 09:57

    const_castをつかわないほうがいい。しないほうがいいんでしょ。という話だったようですが、mulの命令だけを説明するなりなんなりして、書き込まなきゃ別にそれでもいいけど、もうスレをあげないでほしいぐらいに感じています。以上です。

    キャンセル

-6

手計算したんだけど、double型にしないと精度が駄目でした。

double Frame_Scene_Root[16]={
1.000000,0.000000,0.000000,0.000000,
0.000000,1.000000,0.000000,0.000000,
0.000000,0.000000,1.000000,0.000000,
0.000000,0.000000,0.000000,1.000000};


double Frame_body[16]={

1.278853,0.000000,-0.000000,0.000000,
0.000000,0.000000,1.123165,0.000000,
0.000000,-1.470235,0.000000,0.000000,
0.135977,2.027985,133.967667,1.000000
};

double Frame[16]={

1.000000,-0.000000,-0.000000,0.000000,
-0.000000,1.000000,0.000000,0.000000,
-0.000000,0.000000,1.000000,0.000000,
-0.142114,0.000023,-49.556850,1.000000};


double temp[16];

void Ranks( double *temp ,double* a, double *b)
{
temp[0]=a[0]*b[0]+a[1]*b[4]+a[2]*b[8]+a[3]*b[12];//ok
temp[1]=a[0]*b[1]+a[1]*b[5]+a[2]*b[9]+a[3]*b[13];//ok
temp[2]=a[0]*b[2]+a[1]*b[6]+a[2]*b[10]+a[3]*b[14];//ok
temp[3]=a[0]*b[3]+a[1]*b[7]+a[2]*b[11]+a[3]*b[15];//ok

temp[4]=a[4]*b[0]+a[5]*b[4]+a[6]*b[8]+a[7]*b[12];//ok
temp[5]=a[4]*b[1]+a[5]*b[5]+a[6]*b[9]+a[7]*b[13];//ok
temp[6]=a[4]*b[2]+a[5]*b[6]+a[6]*b[10]+a[7]*b[14];//ok
temp[7]=a[4]*b[3]+a[5]*b[7]+a[6]*b[11]+a[7]*b[15];//ok

temp[8]=a[8]*b[0]+a[9]*b[4]+a[10]*b[8]+a[11]*b[12];//0k
temp[9]=a[8]*b[1]+a[9]*b[5]+a[10]*b[9]+a[11]*b[13];//0k
temp[10]=a[8]*b[2]+a[9]*b[6]+a[10]*b[10]+a[11]*b[14];//0k
temp[11]=a[8]*b[3]+a[9]*b[7]+a[10]*b[11]+a[11]*b[15];//0k

temp[12]=a[12]*b[0]+a[13]*b[4]+a[14]*b[8]+a[15]*b[12];//0k
temp[13]=a[12]*b[1]+a[13]*b[5]+a[14]*b[9]+a[15]*b[13];
temp[14]=a[12]*b[2]+a[13]*b[6]+a[14]*b[10]+a[15]*b[14];
temp[15]=a[12]*b[3]+a[13]*b[7]+a[14]*b[11]+a[15]*b[15];


}

Ranks(&temp[0],&Frame_Scene_Root[0],&Frame_body[0]);

ロジックがあってるかは別として書いてみたんだけどさ、
Frame_Scene_Root[0]とFrame_body[0]がdouble型にできなかったんだが、元の値が変わってしまうのですがどうすべきでしょうか。どこかを、constすればいいのか教えてください

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/30 12:06

    いや、退会はしないけどね。

    キャンセル

  • 2020/08/03 09:59

    端的にはグローバル変数の初期化と、関数のローカル変数の初期化は違う。あなたがやっているのはグローバル変数の初期化を使っているから、プログラムの実行時に1度初期化されているしかし、実際は関数の呼び出し時に毎回初期化する必要があるので、明示的にForをつかって初期化するほうが良い。これはC++の知識だけでも溶けるが、OSやハードの知識もあったほうが問題をときやすい。constはconst記号を付ける位置を変えるとポインタをconstなのか、ポインタの値をconstなのかがかわるいように、初期化も初期化の対象が代わるという比喩。知識は有料であるから、無料で回答といわれると、たしょうは無料感がいるから、すこしぼかしている。本来はconstではなく初期化子のいちがおかしいというほうがよりわかりやすい回答ではあるが、そうすると有料の回答に近づいてしまう。まぁ、こんなもん

    キャンセル

  • 2020/08/03 10:12

    初期化は本題ではないのでどうでもいいです。ファイルやデータベースから読み込むのが最もポピュラーだと思いますが、それを書いてもノイズにしかなりません。

    キャンセル

-11

const char * char * const char * const 

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/08/04 18:37

    コンパイラで1度確認がいりますが マエconst 後constなど前からconstをかけるのか、うしろかかかけるのかで意味が違うというテーマから派生し
    日本語で説明するよりもオリジナルが英語なら英語で回答したほうがプログラムならプログラム言語で回答したほうが早いということから、表題のタイトルで回答しています。

    キャンセル

  • 2020/08/04 18:47 編集

    MUL 一つで行列の乗算ができると言っているわけですか?

    キャンセル

  • 2020/08/06 05:32

    こういうふうに間違える人もいますとおわらいいただければよいのでしょう
    お時間をちょうだいすることになり
    もうしわけない というのとは違いますが謝罪を
     
    誠に申し訳ございませんでした。楽しいひと時をありがとうございました。
    不愉快な思いをさせる意図はございませんでした。
    お詫び申し上げます

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る