2016-02-27 9 views
2

У меня есть Кубик-куба, как головоломка я пытаюсь моделировать в WebGL с помощью Three.js:вращения после вращения не действует, как я Ожидать

enter image description here

Каждый из двух центров окраски может вращаться. Когда они вращаются, они привозят все части вокруг них вдоль вращения. Например, если мы вращаем оранжево-синий центр, это то, что происходит:

rotating around Orange-Blue Center

Когда вы закончите вращение, все, выстраивается:

enter image description here

Однако, теперь, когда я попробуйте повернуть центр Orange-White, я получаю странное поведение для двух частей, которые он унаследовал от центра Orange-Blue после первого поворота:

enter image description here

Я ожидаю, что они будут вращаться, как другие фигуры, но вместо этого они вращаются по-разному.

Я использую Object3D.rotateOnAxis three.js в() функцию, чтобы сделать мои вращения:

function rotate (center, distance) { 
    var axis = center.axis; 
    center.model.rotateOnAxis (axis, distance); 
    for (var i in center.stickers) { 
     center.stickers[i].rotateOnAxis (axis, distance ); 
    } 

    for (var i in center.children) { 
     center.children[i].model.rotateOnAxis (axis, distance); 

     //Note: the stickers are just the colored faces 
     for (var s in center.children[i].stickers) { 
      center.children[i].stickers[s].rotateOnAxis (axis, distance); 
     } 
    } 
} 

Вот что мой ключ-отжимает код выглядит следующим образом:

function showCube() { 
    //set stuff up, then... 

    count = 0; 
    parent.onkeypress = function(event) { 
     if (count < 6) { 
      rotate(blocks.centers [ "BO" ], Math.PI/6); 

      count++; 

      if (count == 6) { 
       moveFace (blocks, "O1", "OY", "BW"); 
       moveFace (blocks, "O2", "OW", "BY"); 

       moveFace (blocks, "B1", "BW", "OY"); 
       moveFace (blocks, "B2", "BY", "OW"); 

       moveCorner (blocks, "BOW", "OW", "OY"); 
       moveCorner (blocks, "BOW", "BW", "BY"); 

       moveCorner (blocks, "BOY", "OY", "OW"); 
       moveCorner (blocks, "BOY", "BY", "BW"); 
      } 

     } else { 
      rotate(blocks.centers [ "OW" ], Math.PI/6); 
     } 
    } 
} 

function moveFace (blocks, child, oldParent, newParent) { 
    var index = blocks.centers [ oldParent ].children.indexOf (blocks.faces [ child ]); 
    blocks.centers [ oldParent ].children.splice (index, 1); 
    blocks.centers [ newParent ].children.push (blocks.faces [ child ]); 
} 

function moveCorner (blocks, child, oldParent, newParent) { 
    var index = blocks.centers [ oldParent ].children.indexOf (blocks.corners [ child ]); 
    blocks.centers [ oldParent ].children.splice (index, 1); 
    blocks.centers [ newParent ].children.push (blocks.corners [ child ]); 
} 

Интересно, чтобы получить синий-оранжево-желтый угол, чтобы вращаться правильно, мне нужно сделать поворот вокруг разницы между вектором BO и вектором OW.

То есть:

  • Сине-оранжевая ось нормированный вектор: (0, 1, 1)
  • Оранжево-белая ось нормализованного вектор: (1, 0, 1)
  • После того, как первое вращение завершено, если я попытаюсь вращать угол BOY вокруг нормали (1, 0, 1), я получаю поведение, показанное в картинах .
  • Однако, если я пытаюсь повернуть его вокруг (0, 1, 1) - (1, 0, 1), то есть (-1, 1, 0), я получаю желаемое поведение.

Я не понимаю, что происходит. Можете ли вы помочь мне обновить мою функцию вращения, чтобы я получил поведение, которое я хочу, не имея необходимости хранить длинный список прошлых поворотов, которые испытывал кусок?

Я подозреваю, что после того, как я сделаю свой первый поворот, мне нужно сказать кусочку «нулевого» состояния его вращения, не вызывая какого-либо движения, но я не совсем уверен, как это сделать, или если это правильный подход ,

Вы можете играть с вещью здесь: http://joshuad.net/clover-cube/so-question/

Спасибо!

ответ

0

Я установил ее, изменив мой поворота метод следующим образом:

function rotate (center, distance) { 
    var axis = center.axis; 
    center.model.rotateOnAxis (axis, distance); 
    applyStatesToMatrixDirectly (center.model); 

    for (var stickerIndex in center.stickers) { 
     center.stickers[stickerIndex].rotateOnAxis (axis, distance ); 
     applyStatesToMatrixDirectly (center.stickers[stickerIndex]); 
    } 

    for (var childIndex in center.children) { 
     center.children[childIndex].model.rotateOnAxis (axis, distance); 
     applyStatesToMatrixDirectly (center.children[childIndex].model); 

     for (var childStickerIndex in center.children[childIndex].stickers) { 
      center.children[childIndex].stickers[childStickerIndex].rotateOnAxis (axis, distance); 
      applyStatesToMatrixDirectly (center.children[childIndex].stickers[childStickerIndex]); 
     } 
    } 
} 

function applyStatesToMatrixDirectly (model) { 
    model.updateMatrix(); 
    model.geometry.applyMatrix(model.matrix); 
    model.position.set(0, 0, 0); 
    model.rotation.set(0, 0, 0); 
    model.scale.set(1, 1, 1) 
    model.updateMatrix(); 
} 

Идея заключается в том, что функция applyStatesToMatrixDirectly() применяется вращение непосредственно к модели матрицы, а затем сбросить все данные вращения (а как и все остальное). Это позволяет модели «забыть», что она была повернута, что позволяет новому rotateOnAxis работать.

Смежные вопросы