Правильный порядок преобразования для графа сцены

Я работаю над быстрым движком WebGL с графом сцен, чтобы быстро создать прототип моей игровой идеи на Reddit ( https://www.reddit.com/r/gameideas/comments/3dsy8m/revolt/). Теперь, после того, как я выполнил некоторые базовые операции рендеринга, я не могу определить правильный порядок, хорошо тот, который выглядит правильным для большинства людей, который я должен использовать для преобразования узлов в графе сцены.

Трудно объяснить, что происходит, но я надеюсь, что вы понимаете, что это не так, как большинство ожидает от этого в любом другом движке.

Вот упрощенная версия того, что я сейчас делаю.

  • Mat4 = glMatrix 0.9.5
  • Utils = Пользовательские утилиты

Узел (Рендер):

@param {parentMatrix}

// Create Local Matrix
self.lMatrix = mat4.create();
mat4.identity(self.lMatrix);
mat4.translate(self.lMatrix, self.position);
mat4.rotate(self.lMatrix, self.rotation[0], [1, 0, 0]);
mat4.rotate(self.lMatrix, self.rotation[1], [0, 1, 0]);
mat4.rotate(self.lMatrix, self.rotation[2], [0, 0, 1]);

var wMatrix = mat4.create();
mat4.identity(wMatrix);
if(parentMatrix){
    mat4.multiply(self.lMatrix, parentMatrix, wMatrix);
}
else{
    mat4.set(self.lMatrix, wMatrix);
}
// Render
var children = this.children,
numChildren = children.length,
child;

for(var i = 0; i < numChildren; i++){
    child = children[i];
    child.render(wMatrix);
}

Entity (Рендер):

@param {parentMatrix}

// Set Transformation matrix
var tMatrix = mat4.create();
mat4.identity(tMatrix);
mat4.translate(tMatrix, self.position);
mat4.rotate(tMatrix, self.rotation[0], [1, 0, 0]);
mat4.rotate(tMatrix, self.rotation[1], [0, 1, 0]);
mat4.rotate(tMatrix, self.rotation[2], [0, 0, 1]);
mat4.scale(tMatrix, self.scale || [1, 1, 1]);

var wMatrix = mat4.create();
mat4.identity(wMatrix);
mat4.multiply(tMatrix, parentMatrix, wMatrix);

Utils.loadTMatrix(wMatrix);
this.texture.bind();
this.mesh.render();

2 ответа

Решение

Я не нашел оригинального способа, на который надеялся, потому что раньше я кешировал матрицы и надеялся продолжать делать это, но теперь я нашел гораздо более простой способ после воссоздания моего старого движка с нуля.

Engine.prototype.NODE.prototype.render = function(parentMatrix){
  var children = this.children,
      numChildren = children.length,
      child, pos, rot, scale;
  // If has set matrix to a copy of it
  if(parentMatrix){
    this.matrix = mat4.clone(parentMatrix);
  }
  else{
    // Else set it to a identity matrix
    mat4.identity(this.matrix);
  }
  // If matrix needs updating reconstruct it
  pos = [this.position.x,
         this.position.y,
         this.position.z];
  rot = [this.rotation.x,
         this.rotation.y,
         this.rotation.z];
  scale = [this.scale.x,
           this.scale.y,
           this.scale.z];
  // Recreate Transformation matrix
  mat4.translate(this.matrix, this.matrix, pos);
  mat4.rotate(this.matrix, this.matrix, rot[0], [1, 0, 0]);
  mat4.rotate(this.matrix, this.matrix, rot[1], [0, 1, 0]);
  mat4.rotate(this.matrix, this.matrix, rot[2], [0, 0, 1]);
  mat4.scale(this.matrix, this.matrix, scale);
  // Render Children with this matrix
  for(var i = 0; i < numChildren; i++){
    child = children[i];
    child.render(this.matrix);
  }
}

Что я в основном делаю, так это то, что если матрица имеет родителя (это не корневой узел), то я начинаю матрицу как клон ее родителя, иначе я устанавливаю матрицу в ее единичную матрицу. Затем применяя к нему регулярные преобразования. Если я найду способ продолжить кеширование матриц, я выложу его как можно скорее.

Обычный порядок - SRT, или масштаб, вращение, затем перевод.

Также я не уверен, что вы можете просто сделать

mat4.rotate(tMatrix, self.rotation[0], [1, 0, 0]); mat4.rotate(tMatrix, self.rotation[1], [0, 1, 0]); mat4.rotate(tMatrix, self.rotation[2], [0, 0, 1]);

с углами Эйлера и получить правильную ориентацию результата. Я не использую углы Эйлера, поэтому я не совсем понимаю детали. Кто-нибудь, пожалуйста, поправьте меня, если я ошибаюсь. Смотрите эту страницу для преобразования между углом Эйлера и матрицей вращения: http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToMatrix/.

Другие вопросы по тегам