From 4f36a2d98dd588e8411a230bb8042c682b2179fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EB=B0=B0=EC=B0=AC=ED=9D=AC?= <cksgml3604@ajou.ac.kr>
Date: Sat, 4 Jun 2022 05:15:08 +0000
Subject: [PATCH] Upload js file

---
 control.js | 1164 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1164 insertions(+)
 create mode 100644 control.js

diff --git a/control.js b/control.js
new file mode 100644
index 0000000..18088b9
--- /dev/null
+++ b/control.js
@@ -0,0 +1,1164 @@
+class deviceData {
+  constructor(lx, ly, lz, gsx, gsy, gsz, oh, op, or){
+    this.lx = lx;
+    this.ly = ly;
+    this.lz = lz;
+    this.gsx = gsx; // (gyro_speed_x) <- angular velocity
+    this.gsy = gsy;
+    this.gsz = gsz;
+    this.oh = oh;
+    this.op = op;
+    this.or = or;
+    this.px = 0.0;
+    this.py = 0.0;
+    this.pz = 0.0;
+    this.ox = 0.0;
+    this.oy = 0.0;
+    this.oz = 0.0;
+  }
+
+  setBaseData(lx, ly, lz, gsx, gsy, gsz, oh, op, or){
+    this.lx = lx;
+    this.ly = ly;
+    this.lz = lz;
+    this.gsx = gsx;
+    this.gsy = gsy;
+    this.gsz = gsz;
+    this.oh = oh;
+    this.op = op;
+    this.or = or;
+  }
+
+  setOH(oh){ this.oh = oh; }
+  setOP(op){ this.op = op; }
+  setOR(or){ this.or = or; }
+
+  setPosX(px){ this.px = px; }
+  setPosY(py){ this.py = py; }
+  setPosZ(pz){ this.pz = pz; }
+
+  setOriX(ox){ this.ox = ox; }
+  setOriY(oy){ this.oy = oy; }
+  setOriZ(oz){ this.oz = oz; }
+
+  reset(){
+    this.px = 0;
+    this.py = 0;
+    this.pz = 0;
+    this.ox = 0;
+    this.oy = 0;
+    this.oz = 0; 
+  }
+
+  getLX() { return this.lx; }
+  getLY() { return this.ly; }
+  getLZ() { return this.lz; }
+  getGSX() { return this.gsx; }
+  getGSY() { return this.gsy; }
+  getGSZ() { return this.gsz; }
+  getOH() { return this.oh; }
+  getOP() { return this.op; }
+  getOR() { return this.or; }
+  getOH() { return this.oh; }
+  getPX() { return this.px; }
+  getPY() { return this.py; }
+  getPZ() { return this.pz; }
+  getOX() { return this.ox; }
+  getOY() { return this.oy; }
+  getOZ() { return this.oz; }
+
+  max() {
+    var m  = -1;
+    if (Math.abs(this.gsx) > Math.abs(this.gsy)) m = 0;
+    else m = 1;
+    if (Math.abs(this.gsz) > Math.abs(this.gsx) && Math.abs(this.gsz) > Math.abs(this.gsy)) m = 2;
+    return m;    
+  }
+
+  moveCheck() {
+    if (this.gsx > 25 || this.gsx < -20 || this.gsy > 25 || this.gsy < -20 || this.gsz > 25 || this.gsz < -20){
+      return true;
+    }
+    return false;
+  }
+}
+
+var mode = -1;
+
+function modeLock() { 
+  if (mode < 0){
+    mode = 100;
+    return true;
+  }
+  return false
+}
+
+function modeRelese(){
+  mode = -1;
+}
+
+var time = [Date.now(), Date.now()];
+var time_diff = 0;
+
+var stopTime = Date.now();
+var lTime = 0;
+var rTime = 0;
+
+var dL = new deviceData(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+var dR = new deviceData(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+var dD = new deviceData(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+var speedL = 0.0;
+var positionL = 0.0;
+var speedR = 0.0;
+var positionR = 0.0;
+
+var orienL = 0.0;
+var orienR = 0.0;
+
+function initLROri() {
+  orienL = 0;
+  orienR = 0;
+}
+
+var angleX = 0;
+var angleY = 0;
+var angleZ = 0;
+
+var preOXL = 0;
+var preOYL = 0;
+var preOZL = 0;
+var preOXR = 0;
+var preOYR = 0;
+var preOZR = 0;
+
+
+var transV = [0.0, 0.0, 0.0];
+
+function reset() {
+  dL.reset(); 
+  dR.reset(); 
+  dD.reset(); 
+  orienL = 0;
+  orienR = 0;
+  angleX = 0;
+  angleY = 0;
+  angleZ = 0;
+  preOXL = 0;
+  preOYL = 0;
+  preOZL = 0;
+  preOXR = 0;
+  preOYR = 0;
+  preOZR = 0;
+}
+
+/*------------------------------input data----------------------------*/
+var firstDevice;
+var secondDevice; 
+// var serviceS;
+// var myCharacteristic;
+
+var started = false;
+function leftScanning(){
+  console.log("starting left scan")
+  navigator.bluetooth.requestDevice({ filters: [{ services: ['0000c001-0000-1000-8000-00805f9b34fb'] }]
+})
+  .then(device => {
+    firstDevice = device;
+    console.log(device)
+    return device.gatt.connect()
+  })
+  .then(server=>{
+    console.log("passing service uuid")
+    return server.getPrimaryService("0000c001-0000-1000-8000-00805f9b34fb");
+  })
+  .then(service=>{
+    console.log("passing service characteristics uuid")
+    return service.getCharacteristic("d7b83c07-eae9-469c-ba5c-12db92c7cfa2");
+  })
+  .then(characteristic=>{
+    console.log("subscribing");
+    characteristic.startNotifications().then(_ => {
+      console.log('> Notifications started');
+      characteristic.addEventListener('characteristicvaluechanged',
+        handleLeftNotifications);
+      started = true;
+    });
+  })
+  .catch(error => { console.error(error.message); });
+};
+
+function rightScanning(){
+    console.log("starting right scan")
+    navigator.bluetooth.requestDevice({ filters: [{ services: ['0000c001-0000-1000-8000-00805f9b34fb'] }]
+  })
+    .then(device => {
+      secondDevice = device;
+      console.log(device)
+      return device.gatt.connect()
+    })
+    .then(server=>{
+      console.log("passing service uuid")
+      return server.getPrimaryService("0000c001-0000-1000-8000-00805f9b34fb");
+    })
+    .then(service=>{
+      console.log("passing service characteristics uuid")
+      return service.getCharacteristic("d7b83c07-eae9-469c-ba5c-12db92c7cfa2");
+    })
+    .then(characteristic=>{
+      console.log("subscribing");
+      characteristic.startNotifications().then(_ => {
+        console.log('> Notifications started');
+        characteristic.addEventListener('characteristicvaluechanged',
+          handleRightNotifications);
+        started = true;
+      });
+    })
+    .catch(error => { console.error(error.message); });
+  };
+
+function fromTwosComplement(twosComplement, numberBytes) 
+{   
+    var numberBits = (numberBytes || 1) * 8;
+    
+    if (twosComplement < 0 || twosComplement > (1 << numberBits) - 1)
+        throw "Two's complement out of range given " + numberBytes + " byte(s) to represent.";
+    
+    // If less than the maximum positive: 2^(n-1)-1, the number stays positive
+    if (twosComplement <= Math.pow(2, numberBits - 1) - 1)
+        return twosComplement;
+    
+    // Else convert to it's negative representation
+    return -(((~twosComplement) & ((1 << numberBits) - 1)) + 1);
+}
+
+function handleLeftNotifications(e) {
+  //handle data here
+  let dataView = new Uint8Array(e.target.value.buffer)
+
+  var pHeading = (dataView[12]<<8) + dataView[13]
+  var pPitch = (dataView[14]<<8) + dataView[15]
+  var pRoll = (dataView[16]<<8) + dataView[17]
+  //pPitch = 65200;
+  if(pPitch != null && pRoll != null){
+    pPitch = fromTwosComplement(pPitch,2);
+    pRoll = fromTwosComplement(pRoll,2);
+    // heading = pPitch > 16383 ? pHeading * 0.011 : 360-(pHeading * 0.011)
+  }
+  else {
+    pHeading = 0;
+    pPitch = 0;
+    pRoll = 0;
+  }
+
+  dL.setBaseData(
+            fromTwosComplement((dataView[2]<<8) + dataView[3],2)*0.000244,
+            fromTwosComplement((dataView[0]<<8) + dataView[1],2)*0.000244,
+            fromTwosComplement((dataView[4]<<8) + dataView[5],2)*0.000244,
+            fromTwosComplement((dataView[10]<<8) + dataView[11],2)*0.061037,
+            fromTwosComplement((dataView[6]<<8) + dataView[7],2)*0.061037,
+            fromTwosComplement((dataView[8]<<8) + dataView[9],2)*0.061037,
+            pHeading * 0.011,
+            pPitch * 0.011,
+            pRoll * 0.011);
+}
+
+function handleRightNotifications(e) {
+   //handle data here
+   let dataView = new Uint8Array(e.target.value.buffer)
+
+   var pHeading = (dataView[12]<<8) + dataView[13]
+   var pPitch = (dataView[14]<<8) + dataView[15]
+   var pRoll = (dataView[16]<<8) + dataView[17]
+   //pPitch = 65200;
+   if(pPitch != null && pRoll != null){
+     pPitch = fromTwosComplement(pPitch,2);
+     pRoll = fromTwosComplement(pRoll,2);
+     // heading = pPitch > 16383 ? pHeading * 0.011 : 360-(pHeading * 0.011)
+   }
+   else {
+     pHeading = 0;
+     pPitch = 0;
+     pRoll = 0;
+   }
+ 
+   dR.setBaseData(
+             fromTwosComplement((dataView[2]<<8) + dataView[3],2)*0.000244148075808,
+             fromTwosComplement((dataView[0]<<8) + dataView[1],2)*0.000244148075808,
+             fromTwosComplement((dataView[4]<<8) + dataView[5],2)*0.000244148075808,
+             fromTwosComplement((dataView[10]<<8) + dataView[11],2)*0.061037018951994,
+             fromTwosComplement((dataView[6]<<8) + dataView[7],2)*0.061037018951994,
+             fromTwosComplement((dataView[8]<<8) + dataView[9],2)*0.061037018951994,
+             pHeading * 0.011,
+             pPitch * 0.011,
+             pRoll * 0.011);
+}
+
+
+  /*------------------------------data control function--------------------*/
+
+
+function sleep(ms) {
+  const wakeUpTime = Date.now() + ms;
+  while (Date.now() < wakeUpTime) {
+      if (Date.now() > wakeUpTime) break;
+  }
+}
+
+function modeOneHandCheck(){
+  if (dL.moveCheck() && !dR.moveCheck()){
+    if (lTime == 0){
+      lTime = Date.now();
+    }
+    else {
+      var timeNow = Date.now();
+      var ldiff = timeNow - stopTime;
+      if (ldiff > 200) {
+        var LM = dL.max();
+        if (LM == 0)
+          mode = modeLock() ? 3 : -1;
+        else if (LM == 1) 
+          mode = modeLock() ? 4 : -1;
+        else
+          mode = modeLock() ? 5 : -1;
+  
+        lTime = 0;
+      }
+    }
+  }
+  else if (!dL.moveCheck() && dR.moveCheck()){
+    if (rTime == 0){
+      rTime = Date.now();
+    }
+    else {
+      var timeNow = Date.now();
+      var rdiff = timeNow - rTime;
+      if (rdiff > 200) {
+        var RM = dR.max();
+        if (RM == 0)
+          mode = modeLock() ? 3 : -1;
+        else if (RM == 1) 
+          mode = modeLock() ? 4 : -1;
+        else
+          mode = modeLock() ? 5 : -1;
+
+        rTime = 0;
+      }
+    }
+  }
+}
+
+function modeReleseCheck(){
+  if(!dL.moveCheck() && !dR.moveCheck()) {
+    if (stopTime == 0){
+      stopTime = Date.now();
+    }
+    else {
+      var timeNow = Date.now();
+      var diff = timeNow - stopTime;
+      if (diff > 2000) {
+        modeRelese();
+        console.log(mode);
+        stopTime = 0;
+      }
+    }
+  }
+}
+
+function modeCheck() {
+  if (mode == -1) {
+    if (dL.moveCheck() && dR.moveCheck()) {
+      var LM = dL.max();
+      var RM = dR.max();
+
+      if (LM == RM){
+        if (LM == 0){
+          if ((dL.getGSX() > 20 && dR.getGSX() > 20) || (dL.getGSX() < -10 && dR.getGSX() < -10)) 
+            mode = modeLock() ? 0 : -1;
+          else if ((dL.getGSX() > 20 && dR.getGSX() < -10) || (dL.getGSX() < -10 && dR.getGSX() > 20)) 
+            mode = modeLock() ? 6 : -1;
+        }
+        else if (LM == 1){
+          if ((dL.getGSY() > 20 && dR.getGSY() > 20) || (dL.getGSY() < -10 && dR.getGSY() < -10)) 
+              mode = modeLock() ? 1 : -1;
+          else if ((dL.getGSY() > 20 && dR.getGSY() < -10) || (dL.getGSY() < -10 && dR.getGSY() > 20)) 
+            mode = modeLock() ? 7 : -1;
+        }
+        else{
+          if ((dL.getGSZ() > 20 && dR.getGSZ() > 20) || (dL.getGSZ() < -10 && dR.getGSZ() < -10)) 
+            mode = modeLock() ? 8 : -1;
+          else if ((dL.getGSZ() > 20 && dR.getGSZ() < -10) || (dL.getGSZ() < -10 && dR.getGSZ() > 20)) 
+            mode = modeLock() ? 2 : -1;
+        }
+      }
+    }
+    else {
+      modeOneHandCheck();
+    }   
+    if (mode > -1) console.log(mode);
+  }
+  else {
+    modeReleseCheck();
+  }
+}
+
+
+
+function recodeSpX() { 
+  if ((dL.getGSX() > 15 || dL.getGSX() < -10) && (dR.getGSX() > 15 || dR.getGSX() < -10)) {
+    orienL = dL.getGSX()*time_diff*0.1;
+    orienR = dR.getGSX()*time_diff*0.1;
+
+    if (mode == 0) { 
+      // x trans
+      dD.setPosX( dD.getPX() + (orienL + orienR) / 2 );
+      dD.setPosX( dD.getPX() > 5 ? 5 : dD.getPX() );
+      dD.setPosX( dD.getPX() < -5 ? -5 : dD.getPX() );
+    }
+    else {
+      // x scale
+      if (orienL > 0 && orienR < 0) {
+        dL.setPosX( dL.getPX() + orienL );
+        dR.setPosX( dR.getPX() + orienR );
+      }
+      else if (dL.getPX() - dR.getPX() > 0) {
+        dL.setPosX( dL.getPX() + orienL );
+        dR.setPosX( dR.getPX() + orienR );
+      }
+      dL.setPosX( dL.getPX() > 5 ? 5 : dL.getPX() );
+      dL.setPosX( dL.getPX() < -5 ? -5 : dL.getPX() );
+      dR.setPosX( dR.getPX() > 5 ? 5 : dR.getPX() );
+      dR.setPosX( dR.getPX() < -5 ? -5 : dR.getPX() );
+    }
+  }
+}
+
+function recodeSpY() { 
+  if ((dL.getGSY() > 15 || dL.getGSY() < -10) && (dR.getGSY() > 15 || dR.getGSY() < -10)) {
+      orienL = dL.getGSY()*time_diff*0.1;
+      orienR = dR.getGSY()*time_diff*0.1;
+  
+      if (mode == 1) { 
+        // y trans
+        dD.setPosY( dD.getPY() + (orienL + orienR) / 2 );
+        dD.setPosY( dD.getPY() > 2 ? 2 : dD.getPY() );
+        dD.setPosY( dD.getPY() < -2 ? -2 : dD.getPY() );
+      }
+      else {
+        // y scale
+        if (orienL < 0 && orienR > 0) {
+          dL.setPosY( dL.getPY() + orienL );
+          dR.setPosY( dR.getPY() + orienR );
+        }
+        else if (-dL.getPY() + dR.getPY() > 0) {
+          dL.setPosY( dL.getPY() + orienL );
+          dR.setPosY( dR.getPY() + orienR );
+        }
+        dL.setPosY( dL.getPY() > 2 ? 2 : dL.getPY() );
+        dL.setPosY( dL.getPY() < -2 ? -2 : dL.getPY() );
+        dR.setPosY( dR.getPY() > 2 ? 2 : dR.getPY() );
+        dR.setPosY( dR.getPY() < -2 ? -2 : dR.getPY() );
+      }
+  }
+}
+
+function recodeSpZ() {
+  if ((dL.getGSZ() > 15 || dL.getGSZ() < -10) && (dR.getGSZ() > 15 || dR.getGSZ() < -10)) {
+      orienL = dL.getGSZ()*time_diff*0.1;
+      orienR = dR.getGSZ()*time_diff*0.1;
+      
+      if (mode == 2) { 
+        // Z trans
+        dD.setPosZ( dD.getPZ() + (-orienL + orienR) / 2 );
+        dD.setPosZ( dD.getPZ() > 7 ? 7 : dD.getPZ() );
+        dD.setPosZ( dD.getPZ() < -2 ? -2 : dD.getPZ() );
+      }
+      else {
+        // Z scale
+        if (orienL < 0 && orienR < 0) {
+          dL.setPosZ( dL.getPZ() + orienL );
+          dR.setPosZ( dR.getPZ() + orienR );
+        }
+        else if (-dL.getPZ() - dR.getPZ() > 0) {
+          dL.setPosZ( dL.getPZ() + orienL );
+          dR.setPosZ( dR.getPZ() + orienR );
+        }
+        dL.setPosZ( dL.getPZ() > 5 ? 5 : dL.getPZ() );
+        dL.setPosZ( dL.getPZ() < -5 ? -5 : dL.getPZ() );
+        dR.setPosZ( dR.getPZ() > 5 ? 5 : dR.getPZ() );
+        dR.setPosZ( dR.getPZ() < -5 ? -5 : dR.getPZ() );
+      }
+  }
+}
+
+function recodeOX() { 
+  if ((dL.getGSX() > 15 || dL.getGSX() < -10) && (dR.getGSX() > 15 || dR.getGSX() < -10)) {
+    var ori_diff_l = dL.getOX() - preOXL;
+    var ori_diff_r = dR.getOX() - preOXR;
+
+    ori_diff_l = ori_diff_l > 100 ? 0 : ori_diff_l;
+    ori_diff_l = ori_diff_l < -100 ? 0 : ori_diff_l;
+    ori_diff_r = ori_diff_r > 100 ? 0 : ori_diff_r;
+    ori_diff_r = ori_diff_r < -100 ? 0 : ori_diff_r;
+    
+    orienL = (dL.getGSX()*time_diff - ori_diff_l) / 2;
+    orienR = (dR.getGSX()*time_diff - ori_diff_r) / 2;
+    angleX = angleX + (orienL + orienR) / 2;
+    dD.setOriX(angleX%360);
+  }
+}
+function recodeOY() { 
+  if ((dL.getGSY() > 15 || dL.getGSY() < -10) && (dR.getGSY() > 15 || dR.getGSY() < -10)) {
+
+    var ori_diff_l = dL.getOY() - preOYL;
+    var ori_diff_r = dR.getOY() - preOYR;
+
+    ori_diff_l = ori_diff_l > 100 ? 0 : ori_diff_l;
+    ori_diff_l = ori_diff_l < -100 ? 0 : ori_diff_l;
+    ori_diff_r = ori_diff_r > 100 ? 0 : ori_diff_r;
+    ori_diff_r = ori_diff_r < -100 ? 0 : ori_diff_r;
+
+    orienL = (dL.getGSY()*time_diff - ori_diff_l) / 2;
+    orienR = (dR.getGSY()*time_diff - ori_diff_r) / 2;
+
+    angleY = angleY + (-orienL+orienR)/2;
+    dD.setOriY(angleY%360);
+  }
+}
+function recodeOZ() {
+  if ((dL.getGSZ() > 15 || dL.getGSZ() < -10) && (dR.getGSZ() > 15 || dR.getGSZ() < -10)) {
+
+    var ori_diff_l = dL.getOZ() - preOZL;
+    var ori_diff_r = dR.getOZ() - preOZR;
+
+    ori_diff_l = ori_diff_l > 100 ? 0 : ori_diff_l;
+    ori_diff_l = ori_diff_l < -100 ? 0 : ori_diff_l;
+    ori_diff_r = ori_diff_r > 100 ? 0 : ori_diff_r;
+    ori_diff_r = ori_diff_r < -100 ? 0 : ori_diff_r;
+    
+    orienL = (dL.getGSZ()*time_diff - ori_diff_l) / 2;
+    orienR = (dR.getGSZ()*time_diff - ori_diff_r) / 2;
+    
+    angleZ = angleZ + (-orienL+orienR)/2;
+    dD.setOriZ(angleZ%360);
+  }
+}
+
+
+function preOrien() {
+  preOXL = dL.getOX();
+  preOYL = dL.getOY();
+  preOZL = dL.getOZ();
+  preOXR = dR.getOX();
+  preOYR = dR.getOY();
+  preOZR = dR.getOZ();
+}
+
+function controlLOH() {
+  if (dL.getOP() < 130 && dL.getOP() > -130)
+    dL.setOriX(dL.getOH());
+}
+
+function controlLOP() {
+  dL.setOriY(dL.getOP());
+}
+
+function controlLOR() {
+  if (dL.getOP() < 135 && dL.getOP() > -135){
+    dL.setOriZ(dL.getOR());
+  }
+}
+
+
+function controlROH() {
+  if (dR.getOP() < 130 && dR.getOP() > -130)
+    dR.setOriX(dR.getOH());
+}
+
+function controlROP() {
+  dR.setOriY(dR.getOP());
+}
+
+function controlROR() {
+  if (dR.getOP() < 135 && dR.getOP() > -135){
+    dR.setOriZ(dR.getOR());
+  }
+}
+
+/*--------------------------------translation Matrix-----------------------*/ 
+
+function scaleLinear(M){
+  scaleV=[1+Math.abs(dL.getPX() - dR.getPX()), 1+Math.abs(-dL.getPY() + dR.getPY()), 1+Math.abs(dL.getPZ() + dR.getPZ())];
+  glMatrix.mat4.scale(M, M, scaleV);
+
+  return M;
+}
+
+function rotateOri(M) {
+  var xaxis = [1.0, 0.0, 0.0];
+  // var yaxis = [0.0, 1.0, 0.0];
+  var zaxis = [0.0, 0.0, 1.0];
+
+  glMatrix.mat4.rotateY(M, M, dD.getOX()*0.0174444); //heading //3.14/180
+  glMatrix.vec3.transformMat4(xaxis, xaxis, M);
+  glMatrix.mat4.rotate(M, M, dD.getOZ()*0.0174444, xaxis);//pitch
+  glMatrix.vec3.transformMat4(zaxis, zaxis, M);
+  glMatrix.mat4.rotate(M, M, dD.getOY()*0.0174444, zaxis);//roll
+  
+  return M;
+}
+
+function moveLinear(M){
+  transV = [dD.getPX(), dD.getPY(), dD.getPZ()]
+  glMatrix.mat4.translate(M, M, transV);
+  return M;
+}
+
+function matrixByMode(){
+  var M = [1.0, 0.0, 0.0, 0.0,
+          0.0, 1.0, 0.0, 0.0,
+          0.0, 0.0, 1.0, 0.0,
+          0.0, 0.0, 0.0, 1.0];
+
+  M = moveLinear(M);
+  M = rotateOri(M);
+  M = scaleLinear(M);
+
+  return M;
+}
+
+/*-----------------------------------Web gl code---------------------------*/
+
+
+//code for cube
+var gl;
+//var texture;
+//var videoE;
+var image;
+var viewMatrixData = new Array(1400);
+
+var minutes = 1000 * 60;
+var hours = minutes * 60;
+var days = hours * 24;
+var years = days * 365;
+var d = new Date();
+var t = d.getTime(); //밀리초
+
+var yt = Math.round(t / years);
+
+function testGLError(functionLastCalled) {
+    var lastError = gl.getError();
+
+    if (lastError != gl.NO_ERROR) {
+        alert(functionLastCalled + " failed (" + lastError + ")");
+        return false;
+    }
+    return true;
+}
+
+function initialiseGL(canvas) {
+    try {
+        // Try to grab the standard context. If it fails, fallback to experimental
+        gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
+        gl.viewport(0, 0, canvas.width, canvas.height);
+    }
+    catch (e) {
+    }
+
+    if (!gl) {
+        alert("Unable to initialise WebGL. Your browser may not support it");
+        return false;
+    }
+    return true;
+}
+
+var vertexData = [
+    // Backface (RED/WHITE) -> z = 0.5
+    -0.5, -0.5, -0.5,  1.0, 0.0, 0.0, 1.0,
+     0.5,  0.5, -0.5,  1.0, 0.0, 0.0, 1.0,
+     0.5, -0.5, -0.5,  1.0, 0.0, 0.0, 1.0,
+    -0.5, -0.5, -0.5,  1.0, 0.0, 0.0, 1.0,
+    -0.5,  0.5, -0.5,  1.0, 0.0, 0.0, 1.0,
+     0.5,  0.5, -0.5,  1.0, 1.0, 1.0, 1.0,
+    // Front (BLUE/WHITE) -> z = 0.5
+    -0.5, -0.5,  0.5,  0.0, 0.0, 1.0, 1.0,
+     0.5,  0.5,  0.5,  0.0, 0.0, 1.0, 1.0,
+     0.5, -0.5,  0.5,  0.0, 0.0, 1.0, 1.0,
+    -0.5, -0.5,  0.5,  0.0, 0.0, 1.0, 1.0,
+    -0.5,  0.5,  0.5,  0.0, 0.0, 1.0, 1.0,
+     0.5,  0.5,  0.5,  1.0, 1.0, 1.0, 1.0,
+    // LEFT (GREEN/WHITE) -> z = 0.5
+    -0.5, -0.5, -0.5,  0.0, 1.0, 0.0, 1.0,
+    -0.5,  0.5,  0.5,  0.0, 1.0, 0.0, 1.0,
+    -0.5,  0.5, -0.5,  0.0, 1.0, 0.0, 1.0,
+    -0.5, -0.5, -0.5,  0.0, 1.0, 0.0, 1.0,
+    -0.5, -0.5,  0.5,  0.0, 1.0, 0.0, 1.0,
+    -0.5,  0.5,  0.5,  0.0, 1.0, 1.0, 1.0,
+    // RIGHT (YELLOE/WHITE) -> z = 0.5
+     0.5, -0.5, -0.5,  1.0, 1.0, 0.0, 1.0,
+     0.5,  0.5,  0.5,  1.0, 1.0, 0.0, 1.0,
+     0.5,  0.5, -0.5,  1.0, 1.0, 0.0, 1.0,
+     0.5, -0.5, -0.5,  1.0, 1.0, 0.0, 1.0,
+     0.5, -0.5,  0.5,  1.0, 1.0, 0.0, 1.0,
+     0.5,  0.5,  0.5,  1.0, 1.0, 1.0, 1.0,
+    // BOTTON (MAGENTA/WHITE) -> z = 0.5
+    -0.5, -0.5, -0.5,  1.0, 0.0, 1.0, 1.0,
+     0.5, -0.5,  0.5,  1.0, 0.0, 1.0, 1.0,
+     0.5, -0.5, -0.5,  1.0, 0.0, 1.0, 1.0,
+    -0.5, -0.5, -0.5,  1.0, 0.0, 1.0, 1.0,
+    -0.5, -0.5,  0.5,  1.0, 0.0, 1.0, 1.0,
+     0.5, -0.5,  0.5,  1.0, 1.0, 1.0, 1.0,
+    // TOP (CYAN/WHITE) -> z = 0.5
+    -0.5,  0.5, -0.5,  0.0, 1.0, 1.0, 1.0,
+     0.5,  0.5,  0.5,  0.0, 1.0, 1.0, 1.0,
+     0.5,  0.5, -0.5,  0.0, 1.0, 1.0, 1.0,
+    -0.5,  0.5, -0.5,  0.0, 1.0, 1.0, 1.0,
+    -0.5,  0.5,  0.5,  0.0, 1.0, 1.0, 1.0,
+     0.5,  0.5,  0.5,  1.0, 1.0, 1.0, 1.0
+];
+
+var screenData = [
+    //screen data, texture plane
+    -1.0, -1.0, -1.0,  
+    -1.0,  1.0, -1.0,  
+     1.0,  1.0, -1.0,  
+    -1.0, -1.0, -1.0,  
+     1.0, -1.0, -1.0,  
+     1.0,  1.0, -1.0  
+];
+
+const textureCoordinates = [
+    // Front
+    0.0,  0.0,
+    0.0,  1.0,
+    1.0,  1.0,
+    0.0,  0.0,
+    1.0,  0.0,
+    1.0,  1.0
+  ];
+
+function initialiseBuffer() {
+
+    gl.vertexBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);
+
+    gl.screenBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.screenBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(screenData), gl.STATIC_DRAW);
+
+    gl.textureBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.textureBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
+
+    return testGLError("initialiseBuffers");
+}
+
+function initTexture() {
+    const texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+
+    var pixel = new Uint8Array([0, 0, 120, 255]);  // opaque blue
+    //gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    return texture;
+}
+
+function updateTexture(texture) {
+    const level = 0;
+    
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
+    gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE);
+}
+
+copyVideo = false;
+
+function initialiseShaders() {
+
+    var fragmentShaderSource1 = '\
+			varying highp vec4 color; \
+			void main(void) \
+			{ \
+				gl_FragColor = color;\
+			}';
+
+    gl.fragShader1 = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(gl.fragShader1, fragmentShaderSource1);
+    gl.compileShader(gl.fragShader1);
+    // Check if compilation succeeded
+    if (!gl.getShaderParameter(gl.fragShader1, gl.COMPILE_STATUS)) {
+        alert("Failed to compile the fragment shader1.\n" + gl.getShaderInfoLog(gl.fragShader1));
+        return false;
+    }
+
+    // Vertex shader code1
+    var vertexShaderSource1 = '\
+			attribute highp vec4 myVertex; \
+			attribute highp vec4 myColor; \
+			uniform mediump mat4 mMat; \
+			uniform mediump mat4 vMat; \
+			uniform mediump mat4 pMat; \
+			varying  highp vec4 color;\
+			void main(void)  \
+			{ \
+				gl_Position = pMat * vMat * mMat * myVertex; \
+				gl_PointSize = 8.0; \
+				color = myColor; \
+			}';
+
+    gl.vertexShader1 = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(gl.vertexShader1, vertexShaderSource1);
+    gl.compileShader(gl.vertexShader1);
+    // Check if compilation succeeded
+    if (!gl.getShaderParameter(gl.vertexShader1, gl.COMPILE_STATUS)) {
+        alert("Failed to compile the vertex shader1.\n" + gl.getShaderInfoLog(gl.vertexShader1));
+        return false;
+    }
+
+    var fragmentShaderSource2 = '\
+            precision mediump float; \
+            varying vec2 vTexture; \
+            uniform sampler2D uSampler; \
+			void main(void) \
+			{ \
+				gl_FragColor = texture2D(uSampler, vTexture); \
+			}';
+
+    gl.fragShader2 = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(gl.fragShader2, fragmentShaderSource2);
+    gl.compileShader(gl.fragShader2);
+    // Check if compilation succeeded
+    if (!gl.getShaderParameter(gl.fragShader2, gl.COMPILE_STATUS)) {
+        alert("Failed to compile the fragment shader2.\n" + gl.getShaderInfoLog(gl.fragShader2));
+        return false;
+    }
+
+    // Vertex shader code2
+    var vertexShaderSource2 = '\
+			attribute vec3 myVertex; \
+			attribute vec2 myTexture; \
+			uniform mediump mat4 mMat; \
+			uniform mediump mat4 vMat; \
+			uniform mediump mat4 pMat; \
+			varying vec2 vTexture; \
+			void main(void)  \
+			{ \
+				gl_Position = pMat * vMat * mMat * vec4(myVertex, 1.0); \
+				vTexture = myTexture; \
+			}';
+
+    gl.vertexShader2 = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(gl.vertexShader2, vertexShaderSource2);
+    gl.compileShader(gl.vertexShader2);
+    // Check if compilation succeeded
+    if (!gl.getShaderParameter(gl.vertexShader2, gl.COMPILE_STATUS)) {
+        alert("Failed to compile the vertex shader2.\n" + gl.getShaderInfoLog(gl.vertexShader2));
+        return false;
+    }
+
+    // Create the shader program
+    gl.programObject1 = gl.createProgram();
+    // Attach the fragment and vertex shaders to it
+    gl.attachShader(gl.programObject1, gl.fragShader1);
+    gl.attachShader(gl.programObject1, gl.vertexShader1);
+    // Bind the custom vertex attribute "myVertex" to location 0
+    gl.bindAttribLocation(gl.programObject1, 0, "myVertex");
+    gl.bindAttribLocation(gl.programObject1, 1, "myColor");
+
+    gl.programObject2 = gl.createProgram();
+    // Attach the fragment and vertex shaders to it
+    gl.attachShader(gl.programObject2, gl.fragShader2);
+    gl.attachShader(gl.programObject2, gl.vertexShader2);
+    gl.bindAttribLocation(gl.programObject2, 2, "myVertex");
+    gl.bindAttribLocation(gl.programObject2, 3, "myTexture");
+    //gl.bindAttribLocation(gl.programObject, 2, "aTexture")
+    // Link the program
+    gl.linkProgram(gl.programObject1);
+    // Check if linking succeeded in a similar way we checked for compilation errors
+    if (!gl.getProgramParameter(gl.programObject1, gl.LINK_STATUS)) {
+        alert("Failed to link the program1.\n" + gl.getProgramInfoLog(gl.programObject1));
+        return false;
+    }
+
+    gl.linkProgram(gl.programObject2);
+    // Check if linking succeeded in a similar way we checked for compilation errors
+    if (!gl.getProgramParameter(gl.programObject2, gl.LINK_STATUS)) {
+        alert("Failed to link the program2.\n" + gl.getProgramInfoLog(gl.programObject2));
+        return false;
+    }
+
+    gl.useProgram(gl.programObject1);
+    gl.useProgram(gl.programObject2);
+
+    return testGLError("initialiseShaders");
+}
+
+
+var tMs = [1.0, 0.0, 0.0, 0.0,
+    0.0, 1.0, 0.0, 0.0,
+    0.0, 0.0, 1.0, 0.0,
+    0.0, 0.0, 0.0, 1.0
+];
+
+function drawTexture(texture){
+    //texture screen 그리기 
+    gl.useProgram(gl.programObject2);
+
+    var worldMatrix = new Float32Array(16);
+    var viewMatrix = new Float32Array(16);
+    var projMatrix = new Float32Array(16);
+
+    glMatrix.mat4.identity(worldMatrix);
+    glMatrix.mat4.identity(viewMatrix);
+
+    var matWorldUniformLocation2 = gl.getUniformLocation(gl.programObject2, 'mMat');
+	var matViewUniformLocation2 = gl.getUniformLocation(gl.programObject2, 'vMat');
+    var matProjUniformLocation2 = gl.getUniformLocation(gl.programObject2, 'pMat');
+
+    
+    //glMatrix.mat4.lookAt(viewMatrix, [0.0, 0.0, 5.0], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]); //viewMatrix가 카메라 
+    glMatrix.mat4.ortho(projMatrix, -1, 1, -1, 1, 0, 1);
+
+    gl.uniformMatrix4fv(matWorldUniformLocation2, gl.FALSE, worldMatrix);
+    gl.uniformMatrix4fv(matViewUniformLocation2, gl.FALSE, viewMatrix);
+    gl.uniformMatrix4fv(matProjUniformLocation2, gl.FALSE, projMatrix);
+
+    if (!testGLError("gl.uniformMatrix4fv")) {
+        return false;
+    }
+
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.screenBuffer);
+    gl.enableVertexAttribArray(2);
+    gl.vertexAttribPointer(2, 3, gl.FLOAT, gl.FALSE, 0, 0);
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.textureBuffer);
+    gl.enableVertexAttribArray(3);
+    gl.vertexAttribPointer(3, 2, gl.FLOAT, gl.FALSE, 0, 0);
+
+    //텍스쳐 적용
+    gl.activeTexture(gl.TEXTURE0);
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.uniform1i(gl.getUniformLocation(gl.programObject2, "uSampler"), 0);
+
+    if (!testGLError("gl.vertexAttribPointer")) {
+        return false;
+    }
+
+    //텍스쳐 스크린 그리는 드로 근데 바인드가 안됨 왜???
+    gl.drawArrays(gl.TRIANGLES, 0, 6); 
+
+    if (!testGLError("gl.drawArrays")) {
+        return false;
+    }
+}
+
+var lookDistance = 5.0;
+function incDistance(){
+    lookDistance += 0.1;
+}
+function decDistance(){
+    lookDistance -= 0.1;
+}
+
+var frames = 0;
+
+function drawCube(){
+    gl.useProgram(gl.programObject1);
+
+    var matWorldUniformLocation1 = gl.getUniformLocation(gl.programObject1, 'mMat');
+	  var matViewUniformLocation1 = gl.getUniformLocation(gl.programObject1, 'vMat');
+    var matProjUniformLocation1 = gl.getUniformLocation(gl.programObject1, 'pMat');
+
+    var tMatrix = new Float32Array(16);
+    glMatrix.mat4.identity(tMatrix);
+    if (started) tMatrix = matrixByMode();
+
+    var worldMatrix = new Float32Array(16);
+    var viewMatrix = new Float32Array(16);
+    var projMatrix = new Float32Array(16);
+
+
+    glMatrix.mat4.identity(worldMatrix);
+    glMatrix.mat4.identity(projMatrix);
+    glMatrix.mat4.lookAt(viewMatrix, [0.0, 0.0, -lookDistance], [0.0, 0.0, 0.0], [0.0, 1.0, 0.0]); //viewMatrix가 카메라 
+    glMatrix.mat4.perspective(projMatrix, glMatrix.glMatrix.toRadian(55.2), 1600.0 / 900.0, 0.1, 15.0); // 0.1 가장 가까운것 1000.0가장 먼것 , projMatrix
+
+    //시간
+    t = new Date().getTime();
+    t = (t - start)/10;
+    t = Math.floor(t);
+    //console.log(t);
+    if(started){
+      //console.clear()
+      //console.log(roll*57.32) 
+    }
+    glMatrix.mat4.mul(worldMatrix, tMatrix, worldMatrix);
+    //glMatrix.mat4.mul(viewMatrix, iMs, viewMatrix); //vM lookAT이후 
+    gl.uniformMatrix4fv(matWorldUniformLocation1, gl.FALSE, worldMatrix);
+    gl.uniformMatrix4fv(matViewUniformLocation1, gl.FALSE, viewMatrix);
+    gl.uniformMatrix4fv(matProjUniformLocation1, gl.FALSE, projMatrix);
+
+    if (!testGLError("gl.uniformMatrix4fv")) {
+        return false;
+    }
+    
+    // */
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
+    gl.enableVertexAttribArray(0);
+    gl.vertexAttribPointer(
+        0, // Attribute location
+        3, // Number of elements per attribute
+        gl.FLOAT, // Type of elements
+        gl.FALSE,
+        28,
+        0 // Offset from the beginning of a single vertex to this attribute
+    );
+    gl.enableVertexAttribArray(1);
+    gl.vertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 28, 12);
+    
+    if (!testGLError("gl.vertexAttribPointer")) {
+        return false;
+    }
+
+    // 큐브 그리기
+    gl.drawArrays(gl.TRIANGLES, 0, 36); 
+
+    if (!testGLError("gl.drawArrays")) {
+        return false;
+    }
+}
+
+function renderScene(texture) {
+
+  gl.clearColor(0.0, 0.0, 0.0, 1.0);
+  gl.clearDepth(1.0);
+
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  gl.disable(gl.DEPTH_TEST);
+
+  drawTexture(texture);
+  gl.enable(gl.DEPTH_TEST);
+
+
+  time[0] = time[1];
+  time[1] = Date.now();
+  time_diff = (time[1]-time[0])*0.001; //second
+
+  modeCheck();
+
+  if (mode == -1){
+    initLROri();
+    i = 0;
+  } 
+  else if (mode == 0) 
+    recodeSpX();
+  else if (mode == 1) 
+    recodeSpY();
+  else if (mode == 2) 
+    recodeSpZ();
+  else if (mode == 3) {
+    controlLOH();
+    controlROH();
+    recodeOX();
+  }
+  else if (mode == 4){
+    controlLOP();
+    controlROP();
+    recodeOY();
+  }
+  else if (mode == 5) {
+    controlLOR();
+    controlROR();
+    recodeOZ();
+  }
+  else if (mode == 6)
+    recodeSpX();
+  else if (mode == 7)
+    recodeSpY();
+  else if (mode == 8) 
+    recodeSpZ();    
+
+  drawCube();
+  preOrien();
+
+  return true;
+}
+
+
+pA = [0, 1, 0];
+tA = [1, 0, 0];
+rA = [0, 0, 1];
+
+function degreeToRadian(deg){
+    var crad = glMatrix.glMatrix.toRadian(deg * 360 / 32767);
+    return crad;
+}
+
+
+/* ----------------------mouse event function-------------------*/
+
+
+var dragging = false;
+var rightclick_count = 0;
+var dblclick_count = 0;
+
+
+function doDoubleClick(evt){
+  if (modeLock()){
+    modeRelese();
+    reset();
+  }
+}
+
+/*------------------------------main function------------------------*/
+
+var start;
+
+function main() {
+
+    const canvas = document.querySelector('#helloapicanvas');
+    this.addEventListener("dblclick", doDoubleClick, false);
+
+    if (!initialiseGL(canvas)) {
+        return;
+    }
+
+
+    if (!initialiseBuffer()) {
+        return;
+    }
+
+    //attriblocation
+
+    if (!initialiseShaders()) {
+        return;
+    }
+
+    const texture = initTexture();
+
+    // Render loop
+    requestAnimFrame = (function () {
+        return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
+      function (callback) {
+          window.setTimeout(callback, 100);
+      };
+    })();
+
+    t = 0;
+    var p = 0;
+    (function renderLoop() {
+      if(!p){
+          t = new Date().getTime();
+          start = t;
+          p = 1;
+      }
+      if (renderScene(texture)) {
+          // Everything was successful, request that we redraw our scene again in the future
+          requestAnimFrame(renderLoop);
+      }
+    })();
+
+  }
-- 
GitLab