If you're seeing this message, it means we're having trouble loading external resources on our website.

Se você está atrás de um filtro da Web, certifique-se que os domínios *.kastatic.org e *.kasandbox.org estão desbloqueados.

Conteúdo principal

Gerando formas 3D

Então agora temos um cubo, mas e se quisermos mudar a sua posição ou tamanho? Ou se quisermos um cuboide retangular ou vários cuboides? Com o nosso código atual, deveremos alterar os nós um por um, o que seria um estorvo. O que gostaríamos é de um métodos simples para criar um cuboide com uma determinada posição e dimensões. Em outras palavras, queremos uma função que mapeie a função e dimensões num arranjo de nós e um arranjo de arestas.

Definindo um cuboide

Um cuboide tem três dimensões: largura, altura e profundidade:
Ele também possui uma posição no espaço tridimensional, nos dando 6 parâmetros. Há algumas maneiras de se definir a posição do cubo: podemos definir seu centro ou um dos vértices. A primeira opção é provavelmente mais comum, mas eu acho a segunda mais fácil de utilizar.
Nossa função precisa retornar tanto o arrnjo de nós quanto o de arestas. Uma forma de retornar duas variáveis é agrupá-las num objeto, com uma chave para nós e outra para arestas. Perceba que você pode utilizar uma string qualquer para referenciar a variável, eu acho mais simples usar a mesma palavra.
// Criar um cuboide com o vértice em (x, y, z)
// com largura, l, altura, h, e profundidade, p.
var criarCuboide = funcao(x, y, z, l, h, p) {
   var nos = [];
   var arestas = [];
   var forma = { 'nodes': nodes, 'edges': edges };
   return forma;
};
Se tivéssemos usado aquela função para criar um cuboide, acessaríamos o primeiro nó da seguinte forma:
var objeto = criarCuboide(0, 0, 0, 100, 160, 50);
var no0 = forma.nos[0];
Isto vai definir no0 para o primeiro valor no arranjo nós. Neste momento, entretanto, não há valores nos arranjos de nós ou arestas.
Definimos os nós como sendo cada combinação de posição, com ou sem a dimensão correspondente. Arestas são definidas da mesma forma de antes (exceto pelo fato de que em vez de definir cada aresta individualmente antes, eu defino todas de uma vez). Note que esta função lhe permite especificar dimensões negativas para o cuboide.
var criarCuboide = function(x, y, z, w, h, d) {
   var nos = [[x, y, z ], [x, y, z+d], [x, y+h, z ], [x, y+h, z+d], [x+w, y, z ], [x+w, y, z+d], [x+w, y+h, z ], [x+w, y+h, z+d]];

   var arestas = [[0, 1], [1, 3], [3, 2], [2, 0], [4, 5], [5, 7], [7, 6], [6, 4], [0, 4], [1, 5], [2, 6], [3, 7]];

   return { 'nos': nos, 'arestas': arestas};
};
Agora podemos criar um cuboide com largura 100, altura 160, profundidade 50 e um nó na origem, assim:
var forma = criarCuboide(0, 0, 0, 100, 160, 50);
Como o nosso código precedente só referencia as variáveis globais nós e arestas, precisamos armazenar as propriedades dos nossos objetos nessas variáveis globais:
var nos = forma.nos; var arestas = forma.arestas;
Você pode ver o código completo abaixo.

Trabalhando com múltiplas formas

Podemos criar formatos com diferentes dimensões, e se quiséssemos mais que uma? Quando quisermos uma variável com número de coisas, um arranjo é útil, portanto, vamos criar um arranjo de formatos.
var forma1 = criarCuboide(-120, -20, -20, 240, 40, 40);
var forma2 = criarCuboide(-120, -50, -30, -20, 100, 60);
var forma3 = criarCuboide( 120, -50, -30, 20, 100, 60);
var formas = [forma1, forma2, forma3];
Agora precisamos modificar as funções display e rotate para funcionar com um array de objetos. Comece fazendo o código exibir as arestas em um laço for que passa por todas as formas:
// Desenhar arestas
linha(arestaCor);
for (var formaNum = 0; formaNum < formas.length; formaNum++) {
   var nos = formas[shapeNum].nos;
   var arestas = formas[shapeNum].arestas;
   for (var e = 0; e < arestas.length; e++) {
      var n0 = arestas[e][0];
      var n1 = arestas[e][1];
      var no0 = nos[n0];
      var no1 = nos[n1];
      alinhar (no0[0], no0[1], no1[0], no1[1]);
   }
}
E um laço for similar para exibir os nós:
// Desenhar nós
preencher(noCor);
semLinha();
for (var formaNum = 0; formaNum < formas.length; formaNum++) {
   var nos = formas[shapeNum].nos;
   for (var n = 0; n < nos.length; n++) {
      var no = nos[n]; elipse(no[0], no[1], noTamanho, noTamanho);
   }
}
Poderíamos adicionar um loop similar para cada uma das funções rotacionar, mas acredito que seja mais flexível passar o arranjo de nós para cada função -desta forma podemos rotacionar os formatos independentes uns dos outros. Por exemplo, a função rotarZ3D() seria assim:
var rotarZ3D = funcao(teta, nos) { ... };
Agora, quando usamos o mouse para rotacionar, temos que percorrer as formas e chamar a função para cada uma:
arrasteMouse = funcao() {
   var dx = mouseX - pmouseX;
   var dy = mouseY - pmouseY;
   for (var formaNum = 0; formaNum < formas.length; formaNum++) {
      var nos = formas[shapeNum].nos;
      rotarY3D(dx, nos);
      rotarX3D(dy, nos);
   }
};
Tenha certeza de ter removido quaisquer outras chamadas às funções rotate que não passam nenhum nó. Você pode ver o código completo abaixo.

Quer participar da conversa?

Você entende inglês? Clique aqui para ver mais debates na versão em inglês do site da Khan Academy.