←Previous | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Next→
//    1550  |                (4)|                       |               |
//    1500  +-------------------+                       |               |
//    1450  |                   |(3)                    |               |
//    1400  |                   +-----------------------+---------------|-------+
//    1350  |                                           |               |    (2)|
//    1300  |                                           |.              |     / |
//    1250  |                                           |               |    /  |
//    1200  |                                           |               |   /   |
//    1150  |                                           | .             |  /    |
//    1100  |                                           |               | /     |
//    1050  |                                           |   .           |       |
//    1000  |                                           |     .         |       |
//     950  |                                           |             / |       |
//     900  |                                           |       +-------+       |
//     850  |                                           |       |   *.  |       |  1400-300*sqrt(3)
//     800  |                                           +-------|  /   .|-------+
//     750  |                                                   |(1)    |
//     700  |                                                   +-------+          1400-400*sqrt(3)=707.18
//     650  |                                                           |
//     600  |                                                           |
//     550  +-----------------------------------------------------------+
//     500  |                                                           |
//     450  |                                                           |
//     400  |                                                           |
//     350  |                                                           |
//     300  |                                                           |
//     250  |                                                           |
//     200  |                                                           |
//     150  |                                                           |
//     100  |                                                           |
//      50  |                                                           |
//       0  +-----------------------------------------------------------+
//                                                  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
//              1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7
//          0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0 5 0
//          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  →+x
//
const KEN_COUNT = 88;
const HAKKEN_COUNT = 52;

const pianoWidth = 1500;
const pianoHeight = 2000;
const pianoDepth = 1000;
const pianoX0 = -750;
const pianoX1 = pianoX0 + pianoWidth;
const pianoY0 = -600;
const pianoY1 = pianoY0 + pianoHeight;
const pianoZ0 = -800;
const pianoZ1 = pianoZ0 + pianoDepth;

const curve1X = pianoX0 + 1300;
const curve1Y = pianoY0 + 1400 - 400 * sqrt (3.0);
const curve1R = 200;
const curve1T0 = 0;
const curve1T1 = 60;

const curve2X = pianoX0 + 1700;
const curve2Y = pianoY0 + 1400;
const curve2R = 600;
const curve2T0 = 240;
const curve2T1 = 180;

const curve3X = pianoX0 + 500;
const curve3Y = pianoY0 + 1400;
const curve3R = 600;
const curve3T0 = 0;
const curve3T1 = 90;

const curve4X = pianoX0 + 500;
const curve4Y = pianoY0 + 1500;
const curve4R = 500;
const curve4T0 = 90;
const curve4T1 = 180;

const yukaOn = true;
const yukaCX = 0;
const yukaCY = 0;
const yukaR = 2000;
const yukaZ0 = pianoZ0 - 75;
const yukaZ1 = pianoZ0;

const yaneOn = true;
const yaneX0 = pianoX0;
const yaneX1 = pianoX1;
const yaneY0 = pianoY0 + 150;
const maeyaneY1 = pianoY0 + 550;
const ooyaneY0 = maeyaneY1;
const yaneY1 = pianoY1;
const yaneZ0 = pianoZ1 - 20;
const yaneZ1 = pianoZ1;
let yanePha1;  //多面体の配列。コピー先
let yanePhaA2;  //多面体の配列の配列。コピー元
let yanePhaN;  //フレーム数-1
let yanePhaK;  //現在位置
let yanePhaD;  //動作方向

const tanaitaOn = true;
const tanaitaX0 = pianoX0;
const tanaitaX1 = pianoX1;
const tanaitaY0 = pianoY0;
const tanaitaY1 = pianoY0 + 700;
const tanaitaZ0 = pianoZ1 - 400;
const tanaitaZ1 = pianoZ1 - 350;

const udegiOn = true;
const udegiX0 = pianoX0;
const udegiX1 = pianoX1;
const udegiY0 = pianoY0;
const udegiY1 = pianoY0 + 250;
const udegiZ0 = tanaitaZ1;
const udegiZ1 = yaneZ0;
const udegiWidth = 50;
const udegiCR2 = 50;
const udegiCY2 = udegiY0 + udegiCR2;
const udegiCZ2 = udegiZ0 + 50;
const udegiCR1 = 100;
const udegiCY1 = udegiCY2 + 25;
const udegiCZ1 = udegiCZ2 + udegiCR2 + udegiCR1;

const gawaitaOn = true;
const gawaitaWidth = 25;
const gawaitaX0 = pianoX0;
const gawaitaX1 = pianoX1;
const gawaitaY0 = udegiY1;
const gawaitaY1 = pianoY1;
const gawaitaZ0 = tanaitaZ1;
const gawaitaZ1 = yaneZ0;

const sokoitaOn = true;
const sokoitaX0 = pianoX0;
const sokoitaX1 = pianoX1;
const sokoitaY0 = tanaitaY1;
const sokoitaZ0 = tanaitaZ1 - 5;
const sokoitaZ1 = tanaitaZ1;

const kuchibouOn = true;
const kuchibouX0 = pianoX0 + udegiWidth;
const kuchibouX1 = pianoX1 - udegiWidth;
const kuchibouY0 = pianoY0 + 2;
const kuchibouY1 = pianoY0 + 25;
const kuchibouZ0 = tanaitaZ1;
const kuchibouZ1 = tanaitaZ1 + 30;

const maekamachiOn = true;
const maekamachiX0 = pianoX0 + udegiWidth;
const maekamachiX1 = pianoX1 - udegiWidth;
const maekamachiY0 = udegiY1 - 30;
const maekamachiY1 = maekamachiY0 + 50;
const maekamachiZ0 = tanaitaZ1 + 50;
const maekamachiZ1 = yaneZ0 - 60;

const kenbanfutaOn = true;
const kenbanfutaX0 = pianoX0 + udegiWidth;
const kenbanfutaX1 = pianoX1 - udegiWidth;
const kenbanfutaY0 = pianoY0;
const kenbanfutaY1 = pianoY0 + 205;
const kenbanfutaZ0 = tanaitaZ1 + 30;
const kenbanfutaZ1 = tanaitaZ1 + 100;
let kenbanfutaPha1;  //多面体の配列。コピー先
let kenbanfutaPhaA2;  //多面体の配列の配列。コピー元
let kenbanfutaPhaN;  //フレーム数-1
let kenbanfutaPhaK;  //現在位置
let kenbanfutaPhaD;  //動作方向。1=開く,-1=閉じる,0=開閉中ではない

const fumendaiOn = true;
const fumendaiX0 = pianoX0 + udegiWidth;
const fumendaiX1 = pianoX1 - udegiWidth;
const fumendaiY0 = maekamachiY0 + 30;
const fumendaiY1 = maekamachiY0 + 300;
const fumendaiZ0 = maekamachiZ1 + 10;
const fumendaiZ1 = maekamachiZ1 + 20;
const fumenbanX0 = fumendaiX0 + 250;
const fumenbanX1 = fumendaiX1 - 250;
const fumenbanY0 = fumendaiY0 + 50;
const fumenbanY1 = fumendaiY1;
const fumenbanZ0 = fumendaiZ0;
const fumenbanZ1 = fumendaiZ1;
let fumendaiPha1;  //多面体の配列。コピー先
let fumendaiPhaA2;  //多面体の配列の配列。コピー元
let fumendaiPhaN;  //フレーム数-1
let fumendaiPhaK;  //現在位置
let fumendaiPhaD;  //動作方向

const kenbanOn = true;
const hakkenWidth = 23.5;  //白鍵の幅と間隔。隙間を含む
const kokkenWidth = 13;  //黒鍵の幅。隙間を含む
const kokkenSpace = 13.5;  //黒鍵の間隔
const kenbanWidth = hakkenWidth * 52;
const kenbanHeight = 145;
const hakkenDepth = 20;
const kokkenDepth = 13;
const kenbanX0 = pianoX0 + (pianoWidth - kenbanWidth) * 0.5;
const kenbanX1 = kenbanX0 + kenbanWidth;
const kenbanY0 = pianoY0 + 25;
const kenbanY1 = kenbanY0 + kenbanHeight;
const kenbanZ0 = tanaitaZ1 + 30;
const kenbanZ1 = kenbanZ0 + hakkenDepth + kokkenDepth;
const kenFront = 50;

const hyoushigiOn = true;
const hyoushigiX0 = pianoX0 + udegiWidth;
const hyoushigiX1 = pianoX1 - udegiWidth;
const hyoushigiY0 = kenbanY0;
const hyoushigiY1 = kenbanY1;
const hyoushigiZ0 = kenbanZ0;
const hyoushigiZ1 = kenbanZ0 + hakkenDepth;
const hyoushigiWidth = kenbanX0 - hyoushigiX0;

const kyakuchuuOn = true;

const spacerOn = true;

const pedalOn = true;
let pedalPha1;
let pedalPhaA2;
let pedalPhaK;

const kibanOn = true;

const ym2151On = true;

const msm6258vOn = true;

const isuOn = true;

const COLOR_BODY = "skyblue";
const COLOR_KOKKEN = "#222222";
const COLOR_HAKKEN = "#eeeeee";
const COLOR_CASTER = "gold";
const COLOR_PEDAL = "gold";
const COLOR_KIBAN = "darkgreen";
const COLOR_ISHI = "#111111";
const COLOR_MOJI = "white";
const COLOR_PIN = "silver";
const COLOR_LIFT = "silver";
const COLOR_ISU = "deepskyblue";
const COLOR_YUKA = "darksalmon";
const COLOR_WAKU = "white";

function makePiano () {

  zentaiHako = [];
  hakoArray = [zentaiHako];

  kenInfoArray = [];



  //箱テスト
  if (false) {
    let ph = phNew ([[-100, -100, -100],  //0
                     [100, -100, -100],  //1
                     [100, 100, -100],  //2
                     [-100, 100, -100],  //3
                     [-200, -200, 100],  //4
                     [200, -200, 100],  //5
                     [200, 200, 100],  //6
                     [-200, 200, 100]],  //7
                    [[0, 4, 7, 3],  //-x
                     [1, 2, 6, 5],  //+x
                     [0, 1, 5, 4],  //-y
                     [2, 3, 7, 6],  //+y
                     [0, 3, 2, 1],  //-z
                     [4, 5, 6, 7]]);  //+z
    cprint (phToString (ph));
    zentaiHako.push (setupPolyhedron (ph, "test", COLOR_WAKU));
  }



  //yuka 床
  if (yukaOn) {
    let ph = phNewCylinderXY (yukaCX, yukaCY, yukaR, yukaZ0 + 1, yukaZ1 - 1);
    let pha = phSplitKXY (ph, 1, 1);
    for (let i = 0; i < pha.length; i++) {
      zentaiHako.push (setupPolyhedron (pha[i], "yuka_" + i, COLOR_YUKA));
    }
  }

  //maeyane 前屋根
  //  大屋根に繋がっている
  //  開けると大屋根の上に乗って大屋根を開けると一緒に傾く
  //  鍵押さえの上の隙間を塞ぐ壁が付いている
  //ooyane 大屋根  おおやね
  //  斜めに開く
  //  本物は鏡面艶出し塗装で内部が反射して見える
  if (yaneOn) {
    let phMaeyane = phNewBox (yaneX0 + 1, yaneX1 - 1,
                              yaneY0 + 1, maeyaneY1 - 1,
                              yaneZ0 + 1, yaneZ1 - 1);
    let phMaekabe = phNewBox (maekamachiX0 + 1, maekamachiX1 - 1,
                              maekamachiY0 + 1, maekamachiY0 + 20 - 1,
                              maekamachiZ1 + 1, yaneZ0 - 1,
                              0, 0,
                              0, 0,
                              0, 1);  //+z open
    let phOoyane = phNewPolygonXY (pgTurtle ("j" + yaneX0 + "," + ooyaneY0 +
                                             " d" +
                                             " a0" +
                                             " f" + (yaneX1 - yaneX0) +
                                             " l90" +
                                             " f" + (curve1Y - ooyaneY0) +
                                             " cl" + (curve1T1 - curve1T0) + "," + curve1R +
                                             " cr" + (curve2T0 - curve2T1) + "," + curve2R +
                                             " cl" + (curve3T1 - curve3T0) + "," + curve3R +
                                             " cl" + (curve4T1 - curve4T0) + "," + curve4R),
                                   [yaneZ0 + 1, yaneZ1 - 1]);
    let pha1 = [phMaeyane, phMaekabe, phOoyane];
    for (let i = 0; i < pha1.length; i++) {
      let ph1 = pha1[i];
      zentaiHako.push (setupPolyhedron (ph1, "yane_" + i, COLOR_BODY));
      setMousedownAction (ph1, "yane");
    }
    const n1 = 20;  //前屋根の回転のフレーム数-1
    const n2 = 20;  //大屋根の回転のフレーム数-1
    const n = n1 + n2 + 1;  //全体のフレーム数-1
    const t11 = rad (-180);  //前屋根の回転の範囲(yz)
    const t21 = rad (-25);  //前屋根と大屋根の回転の範囲(zx)
    const hingeY1 = maeyaneY1;  //前屋根の回転軸
    const hingeZ1 = yaneZ1 + 1;
    const hingeX2 = yaneX0;  //大屋根の回転軸
    const hingeZ2 = yaneZ1 + 1;
    let phaA2 = [];  //多面体の配列の配列
    for (let k = 0; k <= n; k++) {
      let pha2;
      if (k <= n1) {  //前屋根が回転する
        let s = softLanding (k / n1);
        let t = s * t11;
        pha2 = [phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (phMaeyane),
                                                            0, -hingeY1, -hingeZ1),
                                            t),
                                0, hingeY1, hingeZ1),
                phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (phMaekabe),
                                                            0, -hingeY1, -hingeZ1),
                                            t),
                                0, hingeY1, hingeZ1),
                phNewCopy (phOoyane)];
      } else {  //前屋根が回転して大屋根と前屋根が回転する
        let s = softLanding ((k - n1 - 1) / n2);
        let t = s * t21;
        pha2 = [phTranslateXYZ (phRotateZX (phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (phMaeyane),
                                                                                        0, -hingeY1, -hingeZ1),
                                                                        t11),
                                                            -hingeX2, hingeY1, hingeZ1 - hingeZ1),
                                            t), hingeX2, 0, hingeZ2),
                phTranslateXYZ (phRotateZX (phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (phMaekabe),
                                                                                        0, -hingeY1, -hingeZ1),
                                                                        t11),
                                                            -hingeX2, hingeY1, hingeZ1 - hingeZ1),
                                            t), hingeX2, 0, hingeZ2),
                phTranslateXYZ (phRotateZX (phTranslateXYZ (phNewCopy (phOoyane),
                                                            -hingeX2, 0, -hingeZ2),
                                            t),
                                hingeX2, 0, hingeZ2)];
      }
      phaA2[k] = pha2;
    }
    yanePha1 = pha1;  //多面体の配列
    yanePhaA2 = phaA2;  //多面体の配列の配列
    yanePhaN = n;  //フレーム数-1
    yanePhaK = 0;  //現在位置
    yanePhaD = 0;  //動作方向
  }

  //tanaita 棚板
  //  重量を支える板
  if (tanaitaOn) {
    const gap = 0.5;
    let ph = phNewBox (tanaitaX0 + gap, tanaitaX1 - gap,
                       tanaitaY0 + gap, tanaitaY1 - gap,
                       tanaitaZ0 + gap, tanaitaZ1 - gap);
    zentaiHako.push (setupPolyhedron (ph, "tanaita", COLOR_BODY));
  }

  //udegi 腕木
  //  鍵盤の左右の壁
  if (udegiOn) {
    const gap = 0.5;
    //       z                                              74
    //    z1-1 329                                   +--------------+
    //                                               |              |
    //                                               |              |
    //         300                                   |              |
    //                                               |              |
    //                                               |              |
    //                                            129|              |
    //                                               |              |
    //                                               |              |
    //                                               |              |
    //                                               |              |
    //                                               |              |
    //                                    100        |              |
    //         200               *-------------------+              |
    //                           |(1)                |              |
    //                           |                   |              |
    //                           |                   |              |
    //                           |                /  |              |328
    //                        100|                   |              |
    //                           |             *     |              |
    //                           |                   |              |
    //                           |                   |              |
    //                        25 |                   |              |
    //         100+---------+----+-------------------+              |
    //            |         |                                       |
    //            |  *      |                                       |
    //            |/        |50                                     |
    //            |      (2)|                                       |
    //          50+---------*                                       |
    //            |    50                                           |
    //            |                                                 |
    //            |                                                 |
    //            |                                                 |
    //    z0+1   1+---------+----+----+--------------+----+---------+
    //            0        50   75   100            175  200       249
    //            y0                                               y1-1  y
    for (let k = 0; k < 2; k++) {  //0=-x,1=+x
      let x0 = k == 0 ? udegiX0 : udegiX1 - udegiWidth;
      let x1 = x0 + udegiWidth;
      let ph = phNewPolygonYZ (pgTurtle ("j" + udegiY0 + "," + (udegiZ0 + gap) +
                                         " d" +
                                         " a0 f" + (250 - gap) +
                                         " l90 f" + (330 - gap * 2) +
                                         " l90 f" + (75 - gap) +
                                         " l90 f" + (130 - gap) +
                                         " cr90,100" +
                                         " f25" +
                                         " cl90,50"),
                               [x0 + gap, x1 - gap]);
      zentaiHako.push (setupPolyhedron (ph, "udegi_" + k, COLOR_BODY));
    }
  }

  //gawaita 側板 がわいた
  if (gawaitaOn) {
    //+x直線部
    if (true) {
      let ph = phNewBox (gawaitaX1 - gawaitaWidth, gawaitaX1,
                         gawaitaY0, curve1Y,
                         gawaitaZ0, gawaitaZ1,
                         0, 0,
                         1, 1,
                         1, 0);
      zentaiHako.push (setupPolyhedron (ph, "gawaita_0", COLOR_BODY));
    }
    //カーブ1
    if (true) {
      let pha = phNewArcXY (curve1X, curve1Y,
                            curve1R - gawaitaWidth, curve1R,
                            rad (curve1T0), rad (curve1T1),
                            gawaitaZ0, gawaitaZ1,
                            1, 1, 1, 0);
      for (let i = 0; i < pha.length; i++) {
        zentaiHako.push (setupPolyhedron (pha[i], "gawaita_1_" + i, COLOR_BODY));
      }
    }
    //カーブ2
    if (true) {
      let pha = phNewArcXY (curve2X, curve2Y,
                            curve2R, curve2R + gawaitaWidth,
                            rad (curve2T1), rad (curve2T0),
                            gawaitaZ0, gawaitaZ1,
                            1, 1, 1, 0);
      for (let i = 0; i < pha.length; i++) {
        zentaiHako.push (setupPolyhedron (pha[i], "gawaita_2_" + i, COLOR_BODY));
      }
    }
    //カーブ3
    if (true) {
      let pha = phNewArcXY (curve3X, curve3Y,
                            curve3R - gawaitaWidth, curve3R,
                            rad (curve3T0), rad (curve3T1),
                            gawaitaZ0, gawaitaZ1,
                            1, 1, 1, 0);
      for (let i = 0; i < pha.length; i++) {
        zentaiHako.push (setupPolyhedron (pha[i], "gawaita_3_" + i, COLOR_BODY));
      }
    }
    //カーブ4
    if (true) {
      let pha = phNewArcXY (curve4X, curve4Y,
                            curve4R - gawaitaWidth, curve4R,
                            rad (curve4T0), rad (curve4T1),
                            gawaitaZ0, gawaitaZ1,
                            1, 1, 1, 0);
      for (let i = 0; i < pha.length; i++) {
        zentaiHako.push (setupPolyhedron (pha[i], "gawaita_4_" + i, COLOR_BODY));
      }
    }
    //-x直線部
    if (true) {
      let ph = phNewBox (gawaitaX0, gawaitaX0 + gawaitaWidth,
                         gawaitaY0, curve4Y,
                         gawaitaZ0, gawaitaZ1,
                         0, 0,
                         1, 1,
                         1, 0);
      zentaiHako.push (setupPolyhedron (ph, "gawaita_5", COLOR_BODY));
    }
  }

  //sokoita 底板
  //  床が見えないようにするための目隠し
  if (sokoitaOn) {
    const gap = 0.5;
    let ph = phNewPolygonXY (pgTurtle ("j" + sokoitaX0 + "," + (sokoitaY0 + gap) +
                                       " d" +
                                       " a0" +
                                       " f" + (sokoitaX1 - sokoitaX0) +
                                       " l90" +
                                       " f" + (curve1Y - sokoitaY0) +
                                       " cl" + (curve1T1 - curve1T0) + "," + curve1R +
                                       " cr" + (curve2T0 - curve2T1) + "," + curve2R +
                                       " cl" + (curve3T1 - curve3T0) + "," + curve3R +
                                       " cl" + (curve4T1 - curve4T0) + "," + curve4R),
                             [sokoitaZ0 + gap, sokoitaZ1 - gap]);
    zentaiHako.push (setupPolyhedron (ph, "sokoita", COLOR_BODY));
  }

  //kuchibou 口棒 くちぼう
  //  鍵盤の手前の壁
  if (kuchibouOn) {
    const gap = 0.5;
    let ph = phNewBox (kuchibouX0 + gap, kuchibouX1 - gap,
                       kuchibouY0 + gap, kuchibouY1 - gap,
                       kuchibouZ0 + gap, kuchibouZ1 - gap);
    zentaiHako.push (setupPolyhedron (ph, "kuchibou", COLOR_BODY));
  }

  //maekamachi 前框 まえかまち
  //  鍵押さえの奥にある分厚い板
  //  弦の張力を支える構造部材
  //鍵押さえ
  //  鍵盤の奥の壁。エンブレムが描かれている
  //  鍵盤蓋を開けると見えなくなる
  if (maekamachiOn) {
    const gap = 0.5;
    let ph = phNewBox (maekamachiX0 + gap, maekamachiX1 - gap,
                       maekamachiY0 + gap, maekamachiY1 - gap,
                       maekamachiZ0 + gap, maekamachiZ1 - gap);
    zentaiHako.push (setupPolyhedron (ph, "maekamachi", COLOR_BODY));
  }

  //kenbanfuta 鍵盤蓋
  if (kenbanfutaOn) {
    const gap = 0.5;
    //         z           ro
    //         z1 +-------------------+----------------------------------------------------------+
    //            |                   |                                                          |
    //            |                   |                                                          |
    //            |            ri     |                                                          |
    //   z3=z2+ri |       +-----------+----------------------------------------------------------+
    //          ro|       |           |
    //            |       |           |
    //            |     ri|           |
    //            |       |           |
    //            |       |           |
    //   z2=z1-ro +-------+-----------+
    //            |       |
    //            |       |
    //            |       |
    //         z0 +-------+
    //            y0   y2=y3-ri    y3=y0+ro                                                      y1  y
    const x0 = kenbanfutaX0 + gap;
    const x1 = kenbanfutaX1 - gap;
    const y0 = kenbanfutaY0 + gap;
    const y1 = kenbanfutaY1 - gap;
    const z0 = kenbanfutaZ0 + gap;
    const z1 = kenbanfutaZ1 - gap;
    const ro = 50;
    const ri = 35;
    const y3 = y0 + ro;
    const y2 = y3 - ri;
    const z2 = z1 - ro;
    const z3 = z2 + ri;
    const hingeY = y1 - 25;
    const hingeZ = z3;
    let pha1 = [];
    aappend (pha1,
             phNewBox (x0, x1,
                       y3, y1,
                       z3, z1,
                       0, 0,
                       1, 0,
                       0, 0),  //奥の箱。y0面は円弧に繋ぐ
             phNewArcYZ (y3, z2, ri, ro, PI / 2, PI, x0, x1, 1, 1, 0, 0),  //円弧。t0面は奥の箱に繋ぐ。t1面は下の箱に繋ぐ
             phNewBox (x0, x1,
                       y0, y2,
                       z0, z2,
                       0, 0,
                       0, 0,
                       0, 1));  //下の箱。z1面は円弧に繋ぐ
    for (let i = 0; i < pha1.length; i++) {
      let ph1 = pha1[i];
      zentaiHako.push (setupPolyhedron (ph1, "kenbanfuta_" + i, COLOR_BODY));
      setMousedownAction (ph1, "kenbanfuta");
    }
    const n = 20;  //フレーム数-1
    const t0 = 0;  //回転の範囲
    const t1 = rad (-100);
    let phaA2 = [];  //多面体の配列の配列
    for (let k = 0; k <= n; k++) {
      let s = softLanding (k / n);
      let t = (1 - s) * t0 + s * t1;
      let pha2 = [];
      for (let i = 0; i < pha1.length; i++) {
        pha2[i] = phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (pha1[i]),
                                                              0, -hingeY, -hingeZ),
                                              t),
                                  0, hingeY, hingeZ);
      }
      phaA2[k] = pha2;
    }
    kenbanfutaPha1 = pha1;  //多面体の配列
    kenbanfutaPhaA2 = phaA2;  //多面体の配列の配列
    kenbanfutaPhaN = n;  //フレーム数-1
    kenbanfutaPhaK = 0;  //現在位置
    kenbanfutaPhaD = 0;  //動作方向
  }

  //fumendai 譜面台
  //fumenban 譜面板
  //     y
  //               banX0-5                     banX1+5
  //  daiY1 +---------+ +---+---------------+---+ +---------+
  //        |         | |   |               |   | |         |
  //        |         | +---+               +---+ |         |
  //        |         | |                       | |         |
  //        |         | |                       | |         |
  //        |         | |                       | |         |
  //        |         | |                       | |         |
  //  banY0 |         | +-----------------------+ |         |
  //        +---------+---------------------------+---------+ banY0-5
  //        |                                               |
  //  daiY0 +-----------------------------------------------+
  //      daiX0       banX0                   banX1       daiX1  x
  if (fumendaiOn) {
    const gap = 0.5;
    let phDaiFront = phNewBox (fumendaiX0 + gap, fumendaiX1 - gap,
                               fumendaiY0 + gap, fumenbanY0 - gap,
                               fumendaiZ0 + gap, fumendaiZ1 - gap);
    let phDaiLeft = phNewBox (fumendaiX0 + gap, fumenbanX0 - gap,
                              fumenbanY0 + gap, fumendaiY1 - gap,
                              fumendaiZ0 + gap, fumendaiZ1 - gap,
                              0, 0,
                              1, 0,  //-y
                              0, 0);
    let phDaiRight = phNewBox (fumenbanX1 + gap, fumendaiX1 - gap,
                               fumenbanY0 + gap, fumendaiY1 - gap,
                               fumendaiZ0 + gap, fumendaiZ1 - gap,
                               0, 0,
                               1, 0,  //-y
                               0, 0);
    let phBan = phNewPolygonXY (pgTurtle ("j" + (fumenbanX0 + gap) + "," + (fumenbanY0 + gap) +
                                          " d" +
                                          " a0" +
                                          " f" + (fumenbanX1 - fumenbanX0 - gap * 2) +
                                          " l90" +
                                          " f" + (fumenbanY1 - fumenbanY0 - 30 - gap * 2) +
                                          " cl90,30" +
                                          " f" + (fumenbanX1 - fumenbanX0 - 60 - gap * 2) +
                                          " cl90,30"),
                                [fumenbanZ0 + gap, fumenbanZ1 - gap]);
    let pha1 = [phDaiFront, phDaiLeft, phDaiRight, phBan];
    for (let i = 0; i < pha1.length; i++) {
      let ph1 = pha1[i];
      zentaiHako.push (setupPolyhedron (ph1, "fumendai_" + i, COLOR_BODY));
      setMousedownAction (ph1, "fumendai");
    }
    const n1 = 10;  //譜面台と譜面板の移動のフレーム数-1
    const n2 = 10;  //譜面板の回転のフレーム数-1
    const n = n1 + n2 + 1;  //全体のフレーム数-1
    const dy10 = 0;  //譜面台と譜面板の移動の範囲
    const dy11 = -75;
    const t20 = 0;  //譜面板の回転の範囲
    const t21 = rad (75);
    const hingeY = fumenbanY0;  //回転軸の移動前の位置
    const hingeZ = fumenbanZ1;
    let phaA2 = [];  //多面体の配列の配列
    for (let k = 0; k <= n; k++) {
      let pha2;
      if (k <= n1) {  //譜面台と譜面板が移動する
        let s = softLanding (k / n1);
        let dy = (1 - s) * dy10 + s * dy11;
        pha2 = [];
        for (let i = 0; i < pha1.length; i++) {
          pha2[i] = phTranslateXYZ (phNewCopy (pha1[i]), 0, dy, 0);
        }
      } else {  //譜面台と譜面板が移動して譜面板が回転する
        let s = softLanding ((k - n1 - 1) / n2);
        let t = (1 - s) * t20 + s * t21;
        pha2 = [];
        for (let i = 0; i < 3; i++) {
          pha2[i] = phTranslateXYZ (phNewCopy (pha1[i]), 0, dy11, 0);
        }
        for (let i = 3; i < pha1.length; i++) {
          pha2[i] = phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (pha1[i]),
                                                                0, -hingeY, -hingeZ),
                                                t),
                                    0, hingeY + dy11, hingeZ);
        }
      }
      phaA2[k] = pha2;
    }
    fumendaiPha1 = pha1;  //多面体の配列
    fumendaiPhaA2 = phaA2;  //多面体の配列の配列
    fumendaiPhaN = n;  //フレーム数-1
    fumendaiPhaK = 0;  //現在位置
    fumendaiPhaD = 0;  //動作方向
  }

  //kenban 鍵盤
  if (kenbanOn) {
    //枠
    let kenbanWaku = phNewBox (kenbanX0, kenbanX1,
                               kenbanY0, kenbanY1,
                               tanaitaZ1, kenbanZ1,
                               1, 1, 1, 1, 1, 1);
    zentaiHako.push (setupPolyhedron (kenbanWaku, "kenban_waku", COLOR_WAKU));
    kenbanWaku.ph$isWaku = true;
    kenbanWaku.ph$hakoNumber = hakoArray.length;
    //箱
    let kenbanHako = [];
    hakoArray.push (kenbanHako);
    //
    const gap = 0.5;  //鍵の隙間の半分
    let kn = 0;
    for (let hakkenNumber = 0; hakkenNumber < HAKKEN_COUNT; hakkenNumber++) {
      let x0 = kenbanX0 + hakkenWidth * hakkenNumber;
      let x1 = x0 + hakkenWidth;
      let y0 = kenbanY0;
      let y1 = kenbanY1;
      let z0 = kenbanZ0;
      let zh = kenbanZ0 + hakkenDepth;
      let zk = zh + kokkenDepth;
      let x0p = x0 + gap;
      let x1m = x1 - gap;
      let yf = y0 + kenFront;
      let yfm = yf - gap;
      let yfp = yf + gap;
      let left = 0;
      let right = 0;
      if (hakkenNumber == 0) {
        right = hakkenWidth - kokkenSpace - kokkenWidth * 0.5;
      } else if (hakkenNumber == 51) {
      } else switch (hakkenNumber % 7) {
      case 0:
        left = kokkenWidth * 0.5;
        right = hakkenWidth - kokkenSpace - kokkenWidth * 0.5;
        break;
      case 1:
        left = kokkenWidth * 1.5 + kokkenSpace - hakkenWidth;
        break;
      case 2:
        right = kokkenWidth - (hakkenWidth - kokkenSpace) * 0.5;
        break;
      case 3:
        left = (hakkenWidth - kokkenSpace) * 0.5;
        right = (hakkenWidth - kokkenSpace) * 0.5;
        break;
      case 4:
        left = kokkenWidth - (hakkenWidth - kokkenSpace) * 0.5;
        break;
      case 5:
        right = kokkenWidth * 1.5 + kokkenSpace - hakkenWidth;
        break;
      case 6:
      default:
        left = hakkenWidth - kokkenSpace - kokkenWidth * 0.5;
        right = kokkenWidth * 0.5;
      }
      let pha;
      if (left == 0 && right == 0) {
        //                +-----------+-----------+-----------+
        //               /|                                  /|
        //              / |                                 / |
        //             /  |                                /  |
        //      y1    +-----------+-----------+-----------+   |
        //            |   |                               |   |
        //            |   +           +           +       |   +
        //            |   |                               |   |
        //            |   |                               |   |
        //            |   |                               |   |
        //     yfm    +   |       +           +           +   |
        //            |   |                               |   |
        //            |   +-----------+-----------+-------|---+    z0
        //            |  /                                |  /
        //            | /                                 | /
        //            |/                                  |/
        //      y0    +-----------+-----------+-----------+    zh
        //
        //           x0p         xlp         xrm         x1m
        pha = [phNewBox (x0p, x1m, y0, y1, z0, zh)];
      } else if (left == 0) {
        //                +-----------+-----------+
        //               /|                      /|
        //              / |                     / |
        //             /  |                    /  |
        //      y1    +-----------+-----------+   |
        //            |   |                   |  8|
        //            |  3+-----------+-------|---+-----------+2
        //            |  /|                   |  /           /|
        //            | / |                   | /           / |
        //            |/  |                  9|/           /  |
        //     yfm   7+-----------+-----------+-----------+6  |
        //            |   |                               |   |
        //            |  0+-----------+-----------+-------|---+1   z0
        //            |  /                                |  /
        //            | /                                 | /
        //            |/                                  |/
        //      y0   4+-----------+-----------+-----------+5   zh
        //
        //           x0p         xlp         xrm         x1m
        let xrm = x1 - right - gap;
        pha = [phNewBox (x0p, xrm, yfm, y1, z0, zh,
                         0, 0, 1, 0, 0, 0),  //-y open
               phNew ([[x0p, y0, z0],  //0
                       [x1m, y0, z0],  //1
                       [x1m, yfm, z0],  //2
                       [x0p, yfm, z0],  //3
                       [x0p, y0, zh],  //4
                       [x1m, y0, zh],  //5
                       [x1m, yfm, zh],  //6
                       [x0p, yfm, zh],  //7
                       [xrm, yfm, z0],  //8
                       [xrm, yfm, zh]],  //9
                      [[0, 4, 7, 3],  //-x
                       [1, 2, 6, 5],  //+x
                       [0, 1, 5, 4],  //-y
                       [2, 8, 9, 6],  //+y
                       [3, 7, 9, 8],  //+y open
                       [0, 3, 8, 2, 1],  //-z
                       [4, 5, 6, 9, 7]],  //+z
                      [0, 0, 0, 0, 1, 0, 0])];
      } else if (right == 0) {
        //                            +-----------+-----------+
        //                           /|                      /|
        //                          / |                     / |
        //                         /  |                    /  |
        //      y1                +-----------+-----------+   |
        //                        |  8|                   |   |
        //               3+-------|---+-----------+-------|---+2
        //               /|       |  /                    |  /|
        //              / |       | /                     | / |
        //             /  |      9|/                      |/  |
        //     yfm   7+-----------+-----------+-----------+6  |
        //            |   |                               |   |
        //            |  0+-----------+-----------+-------|---+1   z0
        //            |  /                                |  /
        //            | /                                 | /
        //            |/                                  |/
        //      y0   4+-----------+-----------+-----------+5   zh
        //
        //           x0p         xlp         xrm         x1m
        let xlp = x0 + left + gap;
        pha = [phNewBox (xlp, x1m, yfm, y1, z0, zh,
                         0, 0, 1, 0, 0, 0),  //-y open
               phNew ([[x0p, y0, z0],  //0
                       [x1m, y0, z0],  //1
                       [x1m, yfm, z0],  //2
                       [x0p, yfm, z0],  //3
                       [x0p, y0, zh],  //4
                       [x1m, y0, zh],  //5
                       [x1m, yfm, zh],  //6
                       [x0p, yfm, zh],  //7
                       [xlp, yfm, z0],  //8
                       [xlp, yfm, zh]],  //9
                      [[0, 4, 7, 3],  //-x
                       [1, 2, 6, 5],  //+x
                       [0, 1, 5, 4],  //-y
                       [2, 8, 9, 6],  //+y open
                       [3, 7, 9, 8],  //+y
                       [0, 3, 8, 2, 1],  //-z
                       [4, 5, 6, 9, 7]],  //+z
                      [0, 0, 0, 1, 0, 0, 0])];
      } else {
        //                            +-----------+
        //                           /|          /|
        //                          / |         / |
        //                         /  |        /  |
        //      y1                +-----------+   |
        //                        | 10|       |  8|
        //               3+-------|---+-------|---+-----------+2
        //               /|       |  /        |  /           /|
        //              / |       | /         | /           / |
        //             /  |     11|/         9|/           /  |
        //     yfm   7+-----------+-----------+-----------+6  |
        //            |   |                               |   |
        //            |  0+-----------+-----------+-------|---+1   z0
        //            |  /                                |  /
        //            | /                                 | /
        //            |/                                  |/
        //      y0   4+-----------+-----------+-----------+5   zh
        //
        //           x0p         xlp         xrm         x1m
        let xlp = x0 + left + gap;
        let xrm = x1 - right - gap;
        pha = [phNewBox (xlp, xrm, yfm, y1, z0, zh,
                         0, 0, 1, 0, 0, 0),  //-y open
               phNew ([[x0p, y0, z0],  //0
                       [x1m, y0, z0],  //1
                       [x1m, yfm, z0],  //2
                       [x0p, yfm, z0],  //3
                       [x0p, y0, zh],  //4
                       [x1m, y0, zh],  //5
                       [x1m, yfm, zh],  //6
                       [x0p, yfm, zh],  //7
                       [xrm, yfm, z0],  //8
                       [xrm, yfm, zh],  //9
                       [xlp, yfm, z0],  //10
                       [xlp, yfm, zh]],  //11
                      [[0, 4, 7, 3],  //-x
                       [1, 2, 6, 5],  //+x
                       [0, 1, 5, 4],  //-y
                       [2, 8, 9, 6],  //+y
                       [8, 10, 11, 9],  //+y open
                       [3, 7, 11, 10],  //+y
                       [0, 3, 10, 8, 2, 1],  //-z
                       [4, 5, 6, 9, 11, 7]],  //+z
                      [0, 0, 0, 1, 0, 0, 0])];
      }
      kenInfoArray.push (newKenInfo (kn, pha));
      kn++;
      //黒鍵を作る
      if (right != 0) {  //白鍵の右側に黒鍵がある
        //            11+-------------------+10
        //             /|                  /|
        //            / |                 / |
        //           /  |                /  |
        //          /   |               /   |
        //         /    |              /    |
        //  y1   3+     |             +2    |
        //        |\    |            /|     |
        //        | 7+-------------+6 |     |
        //        |  |  |          |  |     |
        //        |  |  |          |  |     |
        //        |  |  |          |  |     |
        //        |  |  |          |  |     |
        //        |  |  |          |  |     |
        //        |  | 8+----------|--|-----+9
        //        |  | /           |  |    /
        //        |  |/            |  |   /
        //        | 4+-------------+5 |  /
        //        | /               \ | /
        //        |/                 \|/
        //  yfp  0+-------------------+1
        //       xrp                 xkm
        let xrp = x1 - right + gap;
        let xkm = x1 - right + kokkenWidth - gap;
        let pha = [phNew ([[xrp, yfp, zh],  //0
                           [xkm, yfp, zh],  //1
                           [xkm, y1, zh],  //2
                           [xrp, y1, zh],  //3
                           [xrp + 1.5, yfp + 3, zk],  //4
                           [xkm - 1.5, yfp + 3, zk],  //5
                           [xkm - 1.5, y1, zk],  //6
                           [xrp + 1.5, y1, zk],  //7
                           [xrp, yfp, z0],  //8
                           [xkm, yfp, z0],  //9
                           [xkm, y1, z0],  //10
                           [xrp, y1, z0]],  //11
                          [[4, 5, 6, 7],
                           [4, 7, 3, 0],
                           [5, 4, 0, 1],
                           [6, 5, 1, 2],
                           [7, 6, 2, 10, 11, 3],
                           [0, 3, 11, 8],
                           [1, 0, 8, 9],
                           [2, 1, 9, 10],
                           [9, 8, 11, 10]])];
        kenInfoArray.push (newKenInfo (kn, pha));
        kn++;
      }  //if 白鍵の右側に黒鍵がある
    }  //for hakkenNumber
    for (let kn = 0; kn < kenInfoArray.length; kn++) {  //鍵番号
      let ki = kenInfoArray[kn];  //鍵情報
      let pha1 = ki.ki$pha1;  //多面体の配列
      let color = ki.ki$isKokken ? COLOR_KOKKEN : COLOR_HAKKEN;  //色
      let phaA2 = [[], []];  //多面体の配列の配列
      for (let i = 0; i < pha1.length; i++) {
        let ph = pha1[i];  //多面体
        kenbanHako.push (setupPolyhedron (ph, "ken_" + kn + "_" + i, color));
        let polygonArray = ph.ph$polygonArray;
        for (let polygonNumber = 0; polygonNumber < polygonArray.length; polygonNumber++) {
          let polygon = polygonArray[polygonNumber];
          let elementArray = polygon.pg$elementArray;
          for (let screenNumber = 0; screenNumber <= 2; screenNumber++) {
            let element = elementArray[screenNumber];
            addEvent (element, "mousedown", kenInfoMousedown.bind (ki));
            addEvent (element, "mouseup", kenInfoMouseup.bind (ki));
          }
        }
        const hingeY = kenbanY1 + 50;
        const hingeZ = kenbanZ1;
        const t1 = rad (3);
        phaA2[0][i] = phNewCopy (ph);
        phaA2[1][i] = phTranslateXYZ (phRotateYZ (phTranslateXYZ (phNewCopy (ph), 0, -hingeY, -hingeZ), t1), 0, hingeY, hingeZ);
      }
      ki.ki$phaA2 = phaA2;
    }  //for kn
  }
←Previous | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Next→