2015-08-17 11 views
14

Sto visualizzando un semplice toro in WebGL. La rotazione dei vertici funziona bene ma ho un problema con le normali. Quando ruotano attorno a un singolo asse, mantengono la direzione corretta ma quando la rotazione attorno a un secondo asse aumenta, le normali iniziano a ruotare verso l'alto fino a quando una delle rotazioni non è di 180 °, quindi le normali ruotano nell'opposto opposto di ciò loro dovrebbero. Presumo che il problema sia dovuto al quaternione utilizzato per la rotazione, ma non sono stato in grado di determinare cosa è sbagliato.Le normali ruotano in modo errato quando l'oggetto viene ruotato

Ecco una (leggermente modificato, ma dimostra ancora il problema) jsfiddle del mio progetto: https://jsfiddle.net/dt509x8h/1/
Nella html-parte del violino c'è un div che contiene tutti i dati dal obj file Sono lettura per generare il toro (anche se uno più basso).

vertex:

attribute vec4 aVertexPosition; 
attribute vec3 aNormalDirection; 

uniform mat4 uMVPMatrix; 
uniform mat3 uNMatrix; 

varying vec3 nrm; 

void main(void) { 
    gl_Position = uMVPMatrix * aVertexPosition; 
    nrm = aNormalDirection * uNMatrix; 
} 

frammento Shader:

varying vec3 nrm; 

void main(void) { 
    gl_FragColor = vec4(nrm, 1.0); 
} 

Aggiornamento matrici (eseguito quando c'è stato ingresso):

mat4.perspective(pMatrix, Math.PI*0.25, width/height, clipNear, clipFar); //This is actually not run on input, it is just here to show the creation of the perspective matrix 
mat4.fromRotationTranslation(mvMatrix, rotation, position); 
mat3.normalFromMat4(nMatrix, mvMatrix); 

mat4.multiply(mvpMatrix, pMatrix, mvMatrix); 

var uMVPMatrix = gl.getUniformLocation(shaderProgram, "uMVPMatrix"); 
var uNMatrix = gl.getUniformLocation(shaderProgram, "uNMatrix"); 
gl.uniformMatrix4fv(uMVPMatrix, false, mvpMatrix); 
gl.uniformMatrix3fv(uNMatrix, false, nMatrix); 

Creazione del quaternione rotazione (chiamato quando il mouse si è spostato):

var d = vec3.fromValues(lastmousex-mousex, mousey-lastmousey, 0.0); 
var l = vec3.length(d); 
vec3.normalize(d,d); 
var axis = vec3.cross(vec3.create(), d, [0,0,1]); 
vec3.normalize(axis, axis); 

var q = quat.setAxisAngle(quat.create(), a, l*scale); 
quat.multiply(rotation, q, rotation); 

Ruotando il toro soltanto intorno all'asse Y, le normali puntano nella giusta direzione:
Rotating the torus only around the Y-axis
Ruotando il toro attorno a due assi. I normali siano rivolte in tutto il luogo:
Rotating around two axes

Sto usando glMatrix v2.3.2 per tutte le operazioni con le matrici e quaternione.

Aggiornamento: Sembra che ruotando solo intorno all'asse Z (impostando l'asse di ingresso per quat.setAxisAngle esplicitamente [0,0,1], oppure utilizzando quat.rotateZ) causa anche i normali a ruotare in senso opposto.
L'azzeramento del componente z dello axis non aiuta.

Update2: girante da quat.rotateX(q, q, l*scale); quat.rotateY(q, q, l*scale); quat.multiply(rotation, q, rotation); sembra corretto, ma appena rotazione attorno Z viene introdotto i z normali inizia a muoversi.
L'utilizzo della differenza dei valori del mouse x o y invece di l causa lo spostamento di tutte le normali, e quindi l'utilizzo di valori di variazione scale per xey molto diversi.

Update3: l'ordine di moltiplicazione nello shader a uNMatrix * aNormalDirection fa sì che le normali ruotino sempre in modo errato.

+1

Supponiamo che sia "uNMatrix * aNormalDirection;" nel tuo frammento di shader? –

+1

@ WacławJasper L'ho pensato anch'io, ma dopo aver letto un po ', sembra che alcuni abbiano messo la matrice normale a sinistra e [alcuni a destra] (https://www.opengl.org/documentation/specs/version1 .1/glspec1.1/node26.html), a seconda di come è stato creato. Ad ogni modo, cambiando l'ordine, ogni rotazione viene invertita per le normali. – Jave

+1

Questo probabilmente significa che uno dei segni è capovolto da qualche parte. Forse il tuo 'NormalDirection' sta indicando nel modo sbagliato? O forse passare una matrice modelView al vertex shader e calcolare la matrice normale come 'transpose (inverso (modelView))' per vedere se funziona? Oppure pubblica un esempio completo e eseguibile e posso dare un'occhiata a questo. –

risposta

6

Nel mio caso, il problema è stato il modo in cui ho caricato i dati da un file obj. Avevo invertito la posizione z di tutti i vertici, ma le normali venivano generate dai vertici non invertiti.
L'uso di posizioni z invertite e il ribaltamento della moltiplicazione della matrice normale hanno risolto i problemi.

Problemi correlati