https://linen.dev logo
名前に書いた数字分回転をする方法
# forum
f
ほぼそのまんまです。 踏切の赤丸のオブジェクトを名前に入力した数字分(0~360)回転させたいです。 どうすればできますか? わかる方お願いします。
h
まずオブジェクトをY軸を起点に回転する処理についてですが、原点へ移動→回転処理→元の位置に移動→描画という手順で処理をします。描画スクリプトは処理をスタックして実行するので、実質的には逆順で処理を書いていきます。
Copy code
js
    //回転する処理
    GL11.glPushMatrix();
    GL11.glTranslatef(x, y, z);//元の位置に戻る
    GL11.glRotatef(angle, 0, 1, 0);//回転する 引数の2, 3, 4番目は回転軸のベクトルX, Y, Z
    GL11.glTranslatef(-x, -y, -z);//原点へ移動する
    parts.render(renderer);//描画する
    GL11.glPopMatrix();

    //これとほぼ同等の処理がRTM側にも実装されているため、以下のように書くことも可能
    GL11.glPushMatrix();
    renderer.rotate("Y", angle, x, y, z);//移動&回転の処理
    parts.render(renderer);//描画する
    GL11.glPopMatrix();
文字列から特定の要素を抜き出すには正規表現/RegExpを使用します。
Copy code
js
    //文字列から特定の要素を抜き出す(RegExp/正規表現)
    var name = entity.getModelName();//jsonから名前を取得
    var name = entity.getResourceState().getName();//モデル選択画面で設定した名前から取得(多分)
    var angle = 0;
    var match = name.match(/Angle(\d+)/);//文字列中の Angle◯◯ (◯=数字)にマッチする部分を取得
    if (match) {//matchがない場合はスルー
        angle = parseInt(match[1]);//カッコで囲った数字部分 (\d+) の中身を拾って文字列型から数値型に変換
    }
正規表現は結構奥深いので色々調べてみてください
f
ありがとうございます!!
これって var name = entity.getResourceState().getName(); 書いてから
GL11.glPushMatrix(); GL11.glTranslatef(x, y, z); GL11.glRotatef(angle, 0, name, 0); GL11.glTranslatef(-x, -y, -z); parts.render(renderer);//描画する GL11.glPopMatrix();
でいいんですかね?
スクリプトに関して一切知識がないので、、、、
p
nameには具体的にどのような値が入ることを想定していますか?
f
nameには0~360の数字をいれてその分回転させる感じです
p
名前に入力した数字 ということで、実際にはどのような名前ですか?
0 1 ... 360 みたいな感じですか?
f
名前はモデル選択画面のnameに記入した数字ってことです
p
今のことは気にしないでください
そうしましたらname=angleですので、 hiさんのangleの部分にnameが来る感じです。
f
なるほど
p
それと、xyzはそれぞれ取得する必要があるのではと思います。
踏切の赤丸のオブジェクトを回転させたいということで、回転させるには軸があると思います。
その軸の座標を入力する必要があります。
f
軸ってこんな感じですか?
p
試しに90度回転させた画像も見せてもらっていいですか?
f
こんな感じのでしょうか?
p
左側の灯も同じ方向を向く感じですか?
f
はい
そうゆうことです
p
右側の灯につきましては、それでOKです! 左側の灯の座標も取得してください。 この場合はオブジェクトを、本体と、右側の灯、左側の灯に3分割し、スクリプトで回転させながら全て描画するという方式を取ります。
オブジェクトの分割はそのモデリングソフト上で行ってください。
スクリプト中に、オブジェクトをpartsとして登録する処理があるのはご存知ですか?
f
○○ = renderer.registerParts(new Parts("○○"));
これですか?
p
そうです!
hiさんのスクリプトのparts.render~のpartsの部分が○○になります。("○○"と○○は同じ文字にできますが本来は違うものです)
f
最初に ○○ = renderer.registerParts(new Parts("○○")); で、本体(ポールやブランケット)、右側の灯、右側のライト、左側の灯、左側のライト
p
仮にmain,left,rightに分割したとすると、
Copy code
javascript
main.render(renderer);

if(entity){
  var angle = entity.getResourceState().getName();
}else{
  var angle = 0;
};

var x1 = 0;
var y1 = 0;
var z1 = 0;
GL11.glPushMatrix();
 GL11.glTranslatef(x1, y1, z1);
  GL11.glRotatef(angle, 0, 1, 0);
   GL11.glTranslatef(-x1, -y1, -z1);
   left.render(renderer);
GL11.glPopMatrix();

var x2 = 0;
var y2 = 0;
var z2 = 0;
GL11.glPushMatrix();
 GL11.glTranslatef(x2, y2, z2);
  GL11.glRotatef(angle, 0, 1, 0);
   GL11.glTranslatef(-x2, -y2, -z2);
   right.render(renderer);
GL11.glPopMatrix();
でどうでしょう。x1,y1,z1には左灯の軸の座標、x2,y2,z2には右灯の軸の座標が入ります。
f
まじすか!ありがとうございます!
p
Copy code
javascript
main = renderer.registerParts(new Parts("○○"));
left = renderer.registerParts(new Parts("○○"));
right = renderer.registerParts(new Parts("○○"));
f
これで試してみます!
今日はできいないので明日になりますが、出来たら報告させていただきます!
p
クラッシュした場合→実際のスクリプトとクラッシュレポートを送ってください。 回転がおかしい場合→回転軸の座標入力が不正な場合があります。特に桁を間違えている場合が多いです。(各値1/100する)
Blenderしか使えないので他のモデリングソフトはわかりませんが、ここの座標系が入れ替わっていたり(yとzが逆、xが+-逆など)、mm表記なのかm表記なのかcm表記なのかでややこしくなっています(スクリプト上ではm表記)。
f
なるほど
わかりました
クラッシュはしないんですけど描画がされてないです
すみません数値ミスでした、、、
ただ何も設定していないno_nameの場合描画されないんですけどどうしたらいいんですか?
h
angle = "no_name"だと回転処理が成立しないので、デフォルトでangle = 0、nameが数値として成立するときだけangleに当てる必要があります。 例えば整数のみを適用する場合、以下の正規表現とチェック関数を用いて条件分岐を記述します。
Copy code
js
var name = entity.getResourceState().getName();
var angle = 0;//デフォルト値
var pattern = /^-?\d+$/;

if (pattern.test(name) {//pattern(正規表現)に一致するかどうかをチェック
  angle = parseInt(name, 10);//nameを数値型に変換してangleにいれる
}
正規表現の簡単な解説 ・^ ⋯ $ 完全一致のチェック ・-? -が0個か1個ある ・\d+ 数値(1桁)が1個以上繰り返されている
f
なるほど
ありがとうございます
ひーさんが全部書いてたわ
回転の基準位置。。。❓ 固定じゃダメなんか。。。❓ スクリプトに書いて固定にすりゃ良くね。。。❓ (変数は出しとくにしても)
指定したいのは要するに警報器の回転角度なんしょ
その件は解決済みと見てるけど
u
頭痛くなってきたな すみません降ります
c
角度以外に同じスクリプトで回転軸(基準)が違うモデルにも対応したいって話じゃないですか?
u
だる。。。確かにモデルの名前なりでやればいいが
"Fumikiri_hoge_xa00ya00za00t00" (x,y,zは回転中心座標、tはthetaの略で角度) みたいな名前にして、正規表現で全部抜き出せばいいんじゃないすか(こなみ) xa00ya00za00xb00yb00zb00ってやれば基準座標増やせるし 正規表現の実装がめんどくなるけど
めんどくさいので俺ならスクリプト分けちゃいますね そんな長くないスクリプトだろうし
c
その話がhttps://discord.com/channels/799152792518393917/1348975303514525769/1348982126850084895 かと思います
u
細やかにスマートに技術を積むより、稚拙でもエディットしやすくて量産効果が高い方が、製造面では歩留を上げられて強いなって思った(こなみ) システムが複雑化するとデバグ大変すよ
f
今のところ
Copy code
var renderClass = 'jp.ngt.rtm.render.MachinePartsRenderer';
importPackage(Packages.org.lwjgl.opengl);
importPackage(Packages.jp.ngt.rtm.render);

//オブジェクト定義
function init(par1, par2) {
      main = renderer.registerParts(new Parts('base'));
    main2 = renderer.registerParts(new Parts('base2'));
    left = renderer.registerParts(new Parts('left'));
      right = renderer.registerParts(new Parts('right'));
    light1 = renderer.registerParts(new Parts('light1'));
    light2 = renderer.registerParts(new Parts('light2'));
}

function render(entity,pass,par3) {

    GL11.glPushMatrix();

    //名前の取得
    if(entity){
        var angle = entity.getResourceState().getName();
    }else{
        var angle = 0;
    };


    var light = renderer.getLightState(entity);

    var x1 = -0.42; //左の警報灯器のX軸
    var y1 = 2.5; //左の警報灯器のY軸
    var z1 = 0; //左の警報灯器のZ軸

    var x2 = 0.42; //右の警報灯器のX軸
    var y2 = 2.5; //右の警報灯器のY軸
    var z2 = 0; //右の警報灯器のZ軸
Copy code
//発光なし
    if(pass == 0){

        //描画
        main.render(renderer); //base描画

        GL11.glPushMatrix();
        GL11.glRotatef(angle, 0, 1, 0);
        main2.render(renderer); //警標描画
        GL11.glPopMatrix();

        GL11.glPushMatrix();
        GL11.glTranslatef(x1, y1, z1);
        GL11.glRotatef(angle, 0, 1, 0);
        GL11.glTranslatef(-x1, -y1, -z1);
        left.render(renderer); //左描画
        light2.render(renderer);
        GL11.glPopMatrix();

        GL11.glPushMatrix();
        GL11.glTranslatef(x2, y2, z2);
        GL11.glRotatef(angle, 0, 1, 0);
        GL11.glTranslatef(-x2, -y2, -z2);
        right.render(renderer); //右描画
        light1.render(renderer);
        GL11.glPopMatrix();

        switch(light) { //レッドストーン信号入力時に発光しない
            case 0:
                GL11.glPushMatrix();
                GL11.glTranslatef(x1, y1, z1);
                GL11.glRotatef(angle, 0, 1, 0);
                GL11.glTranslatef(-x1, -y1, -z1);
                light2.render(renderer);
                GL11.glPopMatrix();
            break;

            case 1:
                GL11.glPushMatrix();
                GL11.glTranslatef(x2, y2, z2);
                GL11.glRotatef(angle, 0, 1, 0);
                GL11.glTranslatef(-x2, -y2, -z2);
                light1.render(renderer);
                GL11.glPopMatrix();
            break;
        }
Copy code
//発光あり
    }else if(pass == 2){

        switch(light) { //レッドストーン信号入力時に発光する
            case 0:
                GL11.glPushMatrix();
                GL11.glTranslatef(x2, y2, z2);
                GL11.glRotatef(angle, 0, 1, 0);
                GL11.glTranslatef(-x2, -y2, -z2);
                light1.render(renderer);
                GL11.glPopMatrix();
            break;

            case 1:
                GL11.glPushMatrix();
                GL11.glTranslatef(x1, y1, z1);
                GL11.glRotatef(angle, 0, 1, 0);
                GL11.glTranslatef(-x1, -y1, -z1);
                light2.render(renderer);
                GL11.glPopMatrix();
            break;
        }
    }
    GL11.glPopMatrix();
}
こんな感じ
まささんのも参考にして
最適化してないのは許して
ただvar x1 = ○○;のところ変えれば軸は変えれる
c
だから私はそこの分岐基準をmodelnameにしようとの話をしてた
でんしゃさんのいうことは分岐じゃなくて値をmodelnameに入れようとのことか
やっぱりこれあっちのスレッドじゃね
u
render直書きがスマートじゃないと考えるなら function render(entity, pass, par3){ var x1 = 999.9999 ; var y1 = 777.77777 ; var z1 = 000.0000; … renderCrossGate(x1, y1, z1, …); // 関数呼び出し } function renderCrossGate(x1, y1, z1, …){ // 呼び出す関数 // 踏切の一連の処理 } とかやるのは? あれ、gl11って引き継ぎ入りましたっけ
c
xa00ya00za00xb00yb00zb00より特定文字で区分して.split()したほうが
実装しやすいのでは
なんとなく座標をモデルネームに入れた場合少々目に見えるのが汚くなるかな
f
そこは仕方ない
(てか気にする人いるのか?)
c
整列順番にも関係するので
気にするかも
f
なるほど
c
・モデル名に座標を入れずに
・分岐もしない(?)方法
u
俺は整列順ミスってもいいように数字の頭に添え字入れるの提案します xaとかtaとか abcdefghでやれば種類ある程度増やせるし 二重フィルタいるけど そうじゃなければ文字数とかで判断するもあり
これ、最初のコンセプトぶっ壊してね? たぶんjsonからいじるなら、なんらかの形でjsonを処理するrtm側が、メソッドを理解してスクリプトにブリッジできなきゃ厳しそうだけど https://discord.com/channels/799152792518393917/1348975303514525769/1348982126850084895
c
そもそもJSONがいらないと思ってる
h
なんか話が複雑になってるので私からの提案ですが、データテーブルを作っておき、名称に応じて必要なデータを引っ張ってくる実装はどうでしょうか?
Copy code
js
    var modelDataList = {
        default: {
            x1: 0.0, y1: 0, z1: 0.0,
            x2: 0.0, y2: 0, z2: 0.0
        },
        fumikiri1: {//fumikiri1 がモデル名に相当する
            x1: 0.25, y1: 0, z1: 0.05,
            x2: -0.25, y2: 0, z2: 0.05
        },
        fumikiri2: {
            x1: 0.5, y1: 0, z1: 0.05,
            x2: -0.5, y2: 0, z2: 0.05
        },
        fumikiri3: {
            x1: 0.125, y1: 0, z1: 0.05,
            x2: -0.125, y2: 0, z2: 0.05
        }
    }

    var modelName = entity.getResourceState().getName();//モデルのjsonで設定した名前
    var axisPos = modelDataList[modelName];//modelDataList[モデル名] でテーブルを引く
    if (axisPos === undefined) axisPos = axisPos.default;//未定義であればmodelDataList.defaultを当てる

    var x1 = axisPos.x1;
    var y1 = axisPos.y1;
    var z1 = axisPos.z1;
    var x2 = axisPos.x2;
    var y2 = axisPos.y2;
    var z2 = axisPos.z2;
c
これ送ろうとしてました
私からも同じ提案です
h
おそらくjsonというのが"モデルの定義のjson"と、"コマブロなどに仕込むjson"で混同しているのではないかなと
f
返信するほうミスった
h
単純にjsonと書くと後者の方式もあるので、できるだけ正確に書いてもらえれば伝わりやすいかなと思います。
u
やりたいことが鋭いと、アプローチが絞られて応対に楽なのはありますね
p
自分ならsplitしますね。
Copy code
javascript
var modelName = entity.getModelName();
var axisList = modelName.split("_")
//axisList.map((item) => isNaN(Number(item)) ? item : Number(item));

var x1 = axisList[1];
var y1 = axisList[2];
var z1 = axisList[3];

var x2 = axisList[4];
var y2 = axisList[5];
var z2 = axisList[6];
例えば"wideSignal_-0.42_2.5_0_0.42_2.5_0"という名前なら axisList[0] = "wideSignal", axisList[1] = -0.42...というふうに続き、axisList[1]の部分から回転軸の座標に入力されます。