} else if (fumendaiPhaK == fumendaiPhaN) {
mouseOpeningClosing = true;
fumendaiPhaD = -1;
}
}
function fumendaiTask () {
fumendaiPhaK = max2 (0, min2 (fumendaiPhaN, fumendaiPhaK + fumendaiPhaD));
let pha1 = fumendaiPha1;
let pha2 = fumendaiPhaA2[fumendaiPhaK];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
if (fumendaiPhaK == fumendaiPhaN) {
fumendaiPhaD = 0;
mouseOpeningClosing = false;
} else if (fumendaiPhaK == 0) {
fumendaiPhaD = 0;
mouseOpeningClosing = false;
}
}
function yaneOpenClose () {
if (fumendaiPhaK != 0) {
return;
}
if (yanePhaK == 0) {
mouseOpeningClosing = true;
yanePhaD = 1;
} else if (yanePhaK == yanePhaN) {
mouseOpeningClosing = true;
yanePhaD = -1;
}
}
function yaneTask () {
yanePhaK = max2 (0, min2 (yanePhaN, yanePhaK + yanePhaD));
let pha1 = yanePha1;
let pha2 = yanePhaA2[yanePhaK];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
if (yanePhaK == yanePhaN) {
yanePhaD = 0;
mouseOpeningClosing = false;
} else if (yanePhaK == 0) {
yanePhaD = 0;
mouseOpeningClosing = false;
}
}
function kenbanfutaOpenClose () {
if (kenbanfutaPhaK == 0) {
mouseOpeningClosing = true;
kenbanfutaPhaD = 1;
} else if (kenbanfutaPhaK == kenbanfutaPhaN) {
mouseOpeningClosing = true;
kenbanfutaPhaD = -1;
}
}
function kenbanfutaTask () {
kenbanfutaPhaK = max2 (0, min2 (kenbanfutaPhaN, kenbanfutaPhaK + kenbanfutaPhaD));
let pha1 = kenbanfutaPha1;
let pha2 = kenbanfutaPhaA2[kenbanfutaPhaK];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
if (kenbanfutaPhaK == kenbanfutaPhaN) {
kenbanfutaPhaD = 0;
mouseOpeningClosing = false;
} else if (kenbanfutaPhaK == 0) {
kenbanfutaPhaD = 0;
mouseOpeningClosing = false;
}
}
function kenDown (ki) {
if (!ki.ki$pressed) {
ki.ki$pressed = true;
ki.ki$sostenuto = false;
let pha1 = ki.ki$pha1;
let pha2 = ki.ki$phaA2[1];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
}
}
function kenUp (ki) {
if (ki.ki$pressed) {
ki.ki$pressed = false;
let pha1 = ki.ki$pha1;
let pha2 = ki.ki$phaA2[0];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
}
}
function movePedal (num, pos) {
if (pedalPhaK[num] != pos) {
pedalPhaK[num] = pos;
let pha1 = pedalPha1[num];
let pha2 = pedalPhaA2[num][pos];
for (let i = 0; i < pha1.length; i++) {
let ph1 = pha1[i];
let ph2 = pha2[i];
phLetCopy (ph1, ph2);
ph1.ph$requested = 7;
}
projectRequested |= 7;
}
}
function kenInfoMousedown (e) {
mouseDownElementType = "ken";
if (!this.ki$pressed) {
kenKeyOn (this);
kenDown (this);
}
consumeEvent (e);
}
function kenInfoMouseup (e) {
mouseDownElementType = "";
if (this.ki$pressed) {
if (pedalPhaK[2] == 0 && !this.ki$sostenuto) {
kenKeyOff (this);
}
kenUp (this);
}
consumeEvent (e);
}
const OPM_PORT_COUNT = 2;
let channelMask = 0;
let channelQueue = [];
for (let channelNumber = 0; channelNumber < 8 * OPM_PORT_COUNT; channelNumber++) {
channelQueue[channelNumber] = channelNumber;
}
function kenKeyOn (kenInfo) {
if (kenInfo.ki$keyOn) {
kenKeyOff (kenInfo);
}
kenInfo.ki$keyOn = true;
mousePlaying = true;
let channelNumber = -1;
for (let i = 0; i < channelQueue.length; i++) {
if ((channelMask & (1 << channelQueue[i])) == 0) {
channelNumber = channelQueue[i];
channelQueue.splice (i, 1);
break;
}
}
if (channelNumber < 0) {
channelNumber = channelQueue[0];
channelQueue.splice (0, 1);
let pn = channelNumber >> 3;
let cn = channelNumber & 7;
postOpmSet (pn, 0x08, cn);
}
channelMask |= 1 << channelNumber;
channelQueue.push (channelNumber);
kenInfo.ki$channelNumber = channelNumber;
setVolume (calculateVolume ());
{
let pn = channelNumber >> 3;
let cn = channelNumber & 7;
postOpmSet (pn, 0x28 + cn, kenInfo.ki$keyCode);
postOpmSet (pn, 0x30 + cn, kenInfo.ki$keyFraction);
postOpmSet (pn, 0x08, ((currentNeiro[1] & 15) << 3) + cn);
}
}
function kenKeyOff (kenInfo) {
if (!kenInfo.ki$keyOn) {
return;
}
kenInfo.ki$keyOn = false;
let channelNumber = kenInfo.ki$channelNumber;
kenInfo.ki$channelNumber = -1;
for (let i = 0; i < channelQueue.length; i++) {
if (channelQueue[i] == channelNumber) {
channelQueue.splice (i, 1);
break;
}
}
channelMask &= ~(1 << channelNumber);
channelQueue.push (channelNumber);
let pn = channelNumber >> 3;
let cn = channelNumber & 7;
postOpmSet (pn, 0x08, cn);
if (channelMask == 0) {
mousePlaying = false;
}
}
let mouseElement = null;
let mousePressed = false;
let mouseMoved = false;
let mouseClickCount = 0;
let mouseShiftKey = false;
let mouseCtrlKey = false;
let mouseAltKey = false;
let mouseButton = 0;
let mouseX = 0;
let mouseY = 0;
let mouseDx = 0;
let mouseDy = 0;
let mouseDw = 0;
let mousePlaying = false;
let mouseRolling = false;
let mouseOpeningClosing = false;
let mouseDownElementType = "";
let projectRequested = 7 << 3;
function startProject () {
projectRequested = 7 << 3;
project ();
projectTimeoutId = setTimeout (tickProject, PROJECT_INTERVAL);
}
function stopProject () {
clearTimeout (projectTimeoutId);
projectTimeoutId = 0;
}
function tickProject () {
if (fumendaiPhaD != 0) {
fumendaiTask ();
}
if (kenbanfutaPhaD != 0) {
kenbanfutaTask ();
}
if (yanePhaD != 0) {
yaneTask ();
}
if (mouseDx || mouseDy || mouseDw) {
projectRequested = 7 << 3;
}
if ((projectRequested & (9 << screenMode)) != 0) {
project ();
}
projectTimeoutId = setTimeout (tickProject, PROJECT_INTERVAL);
}
function setScreenMode (mode) {
if (screenMode != mode) {
stopProject ();
screenMode = mode;
if (mode == 0) {
setDisplay (svgElementArray[1], "none");
setDisplay (svgElementArray[2], "none");
setDisplay (svgElementArray[0], "block");
} else {
setDisplay (svgElementArray[0], "none");
setDisplay (svgElementArray[1], "block");
setDisplay (svgElementArray[2], "block");
}
resetSize ();
startProject ();
setButtonActiveSelected (normalButtonArray, mode != 0, mode == 0);
setButtonActiveSelected (parallelButtonArray, mode != 1, mode == 1);
setButtonActiveSelected (crossButtonArray, mode != 2, mode == 2);
}
}
function toggleFloorFixedMode () {
stopProject ();
floorFixed = !floorFixed;
if (floorFixed) {
latitudeRad = max2 (-PI_2, min2 (PI_2, latitudeRad));
nRotateYZ (nLetIRotateXY (rotationMatrix, -longitudeRad), latitudeRad);
}
startProject ();
setButtonActiveSelected (floorFixedButtonArray, true, floorFixed);
}
function project () {
let dx = mouseDx;
let dy = mouseDy;
let dw = mouseDw;
if (dx) {
mouseDx -= dx;
longitudeRad = frem (longitudeRad - dx * PI, TWOPI);
if (floorFixed) {
nRotateYZ (nLetIRotateXY (rotationMatrix, -longitudeRad), latitudeRad);
} else {
nRotateXY (rotationMatrix, dx * PI);
}
}
if (dy) {
mouseDy -= dy;
if (floorFixed) {
latitudeRad = max2 (-PI_2, min2 (PI_2, latitudeRad + dy * PI));
nRotateYZ (nLetIRotateXY (rotationMatrix, -longitudeRad), latitudeRad);
} else {
latitudeRad = frem (latitudeRad + dy * PI + PI, TWOPI) - PI;
nRotateYZ (rotationMatrix, dy * PI);
}
}
if (dw) {
mouseDw -= dw;
cameraDistanceMm = max2 (minimumCameraDisatanceMm, cameraDistanceMm * (1 + 0.1 * dw));
}
if (screenMode == 0) {
projectScreen (globalScreenArray[0]);
} else {
projectScreen (globalScreenArray[1]);
projectScreen (globalScreenArray[2]);
}
}
let ambient = 0;
let lightPositionArray = [[0, 0, pianoZ1 + 4000],
[pianoX0 - 3000, pianoY0 - 2000, pianoZ0 - 1000],
[pianoX1 + 3000, pianoY0 - 2000, pianoZ0 - 1000],
[pianoX0 - 3000, pianoY1 + 2000, pianoZ0 - 1000],
[pianoX1 + 3000, pianoY1 + 2000, pianoZ0 - 1000]];
let lightColorArray = [[1, 1, 1],
[0.5, 0.5, 0.5],
[0.5, 0.5, 0.5],
[0.1, 0.1, 0.1],
[0.1, 0.1, 0.1]];
function projectScreen (screen) {
let screenNumber = screen.sc$screenNumber;
let screenMask = 1 << screenNumber;
let savedProjectRequested = projectRequested;
projectRequested &= ~(screenMask | (screenMask << 3));
let svgElement = svgElementArray[screenNumber];
let focalLengthPx = screen.sc$focalLengthPx;
let ox = screen.sc$viewX + screen.sc$viewWidth * 0.5;
let oy = screen.sc$viewY + screen.sc$viewHeight * 0.5;
let shiftPx = (screenNumber == 0 ? 0 : screenNumber == screenMode ? 0.25 : -0.25) * pupillaryDistancePx;
let miniatureMatrix = nTranslateX (nScaleS (nNewTranslateY (rotationMatrix,
cameraDistanceMm),
focalLengthPx / focalLengthMm),
2 * shiftPx);
let miniatureLightPositionArray = [];
for (let i = 0; i < lightPositionArray.length; i++) {
miniatureLightPositionArray[i] = wNewTransform (lightPositionArray[i], miniatureMatrix);
}
let hakoVisibleArrayArray = [];
for (let hakoNumber = 0; hakoNumber < hakoArray.length; hakoNumber++) {
let hako = hakoArray[hakoNumber];
let hakoVisibleArray = hakoVisibleArrayArray[hakoNumber] = [];
for (let nakamiNumber = 0; nakamiNumber < hako.length; nakamiNumber++) {
let polyhedron = hako[nakamiNumber];
let faceArray = polyhedron.ph$faceArray;
let polygonArray = polyhedron.ph$polygonArray;
if ((savedProjectRequested & (screenMask << 3)) == 0 &&
(polyhedron.ph$requested & screenMask) == 0 &&
(polyhedron.ph$visible & screenMask) != 0) {
hakoVisibleArray.push (polyhedron);
continue;
}
polyhedron.ph$requested &= ~screenMask;
if (polyhedron.ph$isWaku) {
polyhedron.ph$visible |= screenMask;
} else {
polyhedron.ph$visible &= ~screenMask;
}
let vertexArray = polyhedron.ph$vertexArray;
let miniatureVertexArray = polyhedron.ph$miniatureVertexArray;
let projectedVertexArray = polyhedron.ph$projectedVertexArray;
for (let vn = 0; vn < vertexArray.length; vn++) {
let v = vertexArray[vn];
let mv = miniatureVertexArray[vn];
let pv = projectedVertexArray[vn];
wLetTransform (mv, v, miniatureMatrix);
if (mv[1] <= 0) {
pv[0] = NaN;
} else {
let s = focalLengthPx / mv[1];
pv[0] = ox + s * mv[0] - shiftPx;
pv[1] = oy - s * mv[2];
}
}
let normalArray = polyhedron.ph$normalArray;
let miniatureNormalArray = polyhedron.ph$miniatureNormalArray;
let rgb = colorToRGB (polyhedron.ph$color);
let openArray = polyhedron.ph$openArray;
faceLoop:
for (let faceNumber = 0; faceNumber < faceArray.length; faceNumber++) {
if (openArray[faceNumber]) {
continue;
}
let face = faceArray[faceNumber];
let vertexCount = face.length;
let polygon = polygonArray[faceNumber];
polygon.pg$visible &= ~screenMask;
let miniatureNormal = wLetTransform (miniatureNormalArray[faceNumber], normalArray[faceNumber], rotationMatrix);
for (let i = 0; i < vertexCount; i++) {
if (isNaN (projectedVertexArray[face[i]][0])) {
continue faceLoop;
}
}
let g = [0, 0, 0];
if (false) {
for (let vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
wTranslateW (g, miniatureVertexArray[face[vertexIndex]]);
}
g[0] /= vertexCount;
g[1] /= vertexCount;
g[2] /= vertexCount;
} else {
let xmin = Infinity;
let xmax = -Infinity;
let ymin = Infinity;
let ymax = -Infinity;
let zmin = Infinity;
let zmax = -Infinity;
for (let vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
let w = miniatureVertexArray[face[vertexIndex]];
if (w[0] < xmin) {
xmin = w[0];
}
if (xmax < w[0]) {
xmax = w[0];
}
if (w[1] < ymin) {
ymin = w[1];
}
if (ymax < w[1]) {
ymax = w[1];
}
if (w[2] < zmin) {
zmin = w[2];
}
if (zmax < w[2]) {
zmax = w[2];
}
}
g[0] = (xmin + xmax) * 0.5;
g[1] = (ymin + ymax) * 0.5;
g[2] = (zmin + zmax) * 0.5;
}
let geye = wSubtractW ([0, 0, 0], g);
let cosAngle = wCosAngle (miniatureNormal, geye);
if (cosAngle <= 0) {
continue faceLoop;
}
let points = "";
for (let vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) {
if (0 < vertexIndex) {
points += " ";
}
let p = projectedVertexArray[face[vertexIndex]];
points += p[0] + " " + p[1];
}
let element = polygon.pg$elementArray[screenNumber];
movePolygon (element, points);
let red = ambient;
let green = ambient;
let blue = ambient;
for (let i = 0; i < miniatureLightPositionArray.length; i++) {
let lightColor = lightColorArray[i];
let glight = wNewSubtractW (miniatureLightPositionArray[i], g);
let zarazara = max2 (0, wCosAngle (miniatureNormal, glight));
red += rgb[0] * zarazara * lightColor[0];
green += rgb[1] * zarazara * lightColor[1];
blue += rgb[2] * zarazara * lightColor[2];
}
let color = RGBtoColor ([red, green, blue]);
setFill (element, color);
setStroke (element, color);
polygon.pg$visible |= screenMask;
polyhedron.ph$visible |= screenMask;
}
if ((polyhedron.ph$visible & screenMask) != 0) {
hakoVisibleArray.push (polyhedron);
}
}
}
inversedCamera = wTransform ([0, 0, 0], nNewInverse (miniatureMatrix));
for (let hakoNumber = 0; hakoNumber < hakoArray.length; hakoNumber++) {
inferentialSort (hakoVisibleArrayArray[hakoNumber], comparator);
}
let newVisibleArray = hakoVisibleArrayArray[0].concat ();
for (let i = 0; i < newVisibleArray.length; i++) {
let ph = newVisibleArray[i];
if (ph.ph$isWaku) {
let hakoVisibleArray = hakoVisibleArrayArray[ph.ph$hakoNumber];
Array.prototype.splice.apply (newVisibleArray, [i, 1, ...hakoVisibleArray]);
i--;
}
}
removeNode (svgElement, controlPanelArray[screenNumber]);
let oldVisibleArray = screen.sc$visibleArray[screenNumber];
for (let k = oldVisibleArray.length - 1; 0 <= k; k--) {
let polyhedron = oldVisibleArray[k];
let polygonArray = polyhedron.ph$polygonArray;
for (let i = polygonArray.length - 1; 0 <= i; i--) {
let polygon = polygonArray[i];
if ((polygon.pg$displayed & screenMask) != 0) {
removeNode (svgElement, polygon.pg$elementArray[screenNumber]);
polygon.pg$displayed &= ~screenMask;
}
}
}
for (let k = 0; k < newVisibleArray.length; k++) {
let polyhedron = newVisibleArray[k];
let polygonArray = polyhedron.ph$polygonArray;
for (let i = polygonArray.length - 1; 0 <= i; i--) {
let polygon = polygonArray[i];
if ((polygon.pg$visible & screenMask) != 0) {
appendNode (svgElement, polygon.pg$elementArray[screenNumber]);
polygon.pg$displayed |= screenMask;
}
}
}
screen.sc$visibleArray[screenNumber] = newVisibleArray;
appendNode (svgElement, controlPanelArray[screenNumber]);
}
let comparatorWork1 = wNewZero ();
let comparatorWork2 = [];
let comparatorWork3 = wNewZero ();
let comparatorWork4 = nNewIdentity ();
function comparator (ph1, ph2) {
const eps = 1e-4;
let result = 0;
comparator:
for (let sign = 1; -1 <= sign; sign -= 2) {
let rm1 = ph1.ph$reciprocalMatrix;
let rmr1 = nLetRotationComponent (comparatorWork4, rm1);
let a = wLetTransform (comparatorWork1, inversedCamera, rm1);
let ax = a[0];
let ay = a[1];
let az = a[2];
let va2 = ph2.ph$vertexArray;
let va2l = va2.length;
let va = comparatorWork2;
for (let i = va.length; i < va2l; i++) {
va[i] = wNewZero ();
}
for (let i = 0; i < va2l; i++) {
wLetTransform (va[i], va2[i], rm1);
}
let fa2 = ph2.ph$faceArray;
let fa2l = fa2.length;
let na2 = ph2.ph$normalArray;
for (let i = 0; i < fa2l; i++) {
let f2 = fa2[i];
let n = wLetTransform (comparatorWork3, na2[i], rmr1);
let v0 = va[f2[0]];
if ((ax - v0[0]) * n[0] + (ay - v0[1]) * n[1] + (az - v0[2]) * n[2] < eps) {
continue;
}
let f2l = f2.length;
for (let j = 0; j < f2l; j++) {
let b = va[f2[j]];
let bx = b[0];
let by = b[1];
let bz = b[2];
if (ax < -eps) {
const cx = 0;
let cy = ((ax - cx) * by - ay * (bx - cx)) / (ax - bx);
let cz = ((ax - cx) * bz - az * (bx - cx)) / (ax - bx);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
if (1 + eps < ax) {
const cx = 1;
let cy = ((ax - cx) * by - ay * (bx - cx)) / (ax - bx);
let cz = ((ax - cx) * bz - az * (bx - cx)) / (ax - bx);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
if (ay < -eps) {
const cy = 0;
let cz = ((ay - cy) * bz - az * (by - cy)) / (ay - by);
let cx = ((ay - cy) * bx - ax * (by - cy)) / (ay - by);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
if (1 + eps < ay) {
const cy = 1;
let cz = ((ay - cy) * bz - az * (by - cy)) / (ay - by);
let cx = ((ay - cy) * bx - ax * (by - cy)) / (ay - by);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
if (az < -eps) {
const cz = 0;
let cx = ((az - cz) * bx - ax * (bz - cz)) / (az - bz);
let cy = ((az - cz) * by - ay * (bz - cz)) / (az - bz);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
if (1 + eps < az) {
const cz = 1;
let cx = ((az - cz) * bx - ax * (bz - cz)) / (az - bz);
let cy = ((az - cz) * by - ay * (bz - cz)) / (az - bz);
if (-eps < cx && cx < 1 + eps &&
-eps < cy && cy < 1 + eps &&
-eps < cz && cz < 1 + eps) {
let dot = (ax - cx) * (bx - cx) + (ay - cy) * (by - cy) + (az - cz) * (bz - cz);
if (eps < dot) {
result = -sign;
break comparator;
}
if (dot < -eps) {
result = sign;
break comparator;
}
}
}
}
for (let j = 0; j < f2l; j++) {
let b = va[f2[j]];
let bx = b[0];
let by = b[1];
let bz = b[2];
let c = va[f2[j + 1 < f2l ? j + 1 : 0]];
let cx = c[0];
let cy = c[1];
let cz = c[2];
let p = (by - ay) * (cz - az) - (cy - ay) * (bz - az);
let q = (bz - az) * (cx - ax) - (cz - az) * (bx - ax);
let r = (bx - ax) * (cy - ay) - (cx - ax) * (by - ay);
let s = -(p * ax + q * ay + r * az);