diff --git a/Resources/Shaders/oolite-default-planet.vertex b/Resources/Shaders/oolite-default-planet.vertex index 8a7e4507..88873431 100644 --- a/Resources/Shaders/oolite-default-planet.vertex +++ b/Resources/Shaders/oolite-default-planet.vertex @@ -22,7 +22,7 @@ */ // No vNormal, because normal is always 0,0,1 in tangent space. -uniform mat4 ooliteNormalMatrix; +uniform mat3 ooliteNormalMatrix; uniform mat4 ooliteModelView; uniform mat4 ooliteModelViewProjection; uniform mat4 ooliteProjection; @@ -37,8 +37,8 @@ void main(void) vCoords = gl_Vertex.xyz; // Build tangent basis. - vec3 normal = normalize(mat3(ooliteNormalMatrix) * gl_Normal); - vec3 binormal = normalize(cross(normal, mat3(ooliteNormalMatrix) * vec3(0, 1, 0))); + vec3 normal = normalize(ooliteNormalMatrix * gl_Normal); + vec3 binormal = cross(normal, ooliteNormalMatrix * vec3(0, 1, 0)); vec3 tangent = -cross(normal, binormal); mat3 TBN = mat3(tangent, binormal, normal); diff --git a/src/Core/Materials/OOShaderProgram.m b/src/Core/Materials/OOShaderProgram.m index cb45d272..6d9046ff 100644 --- a/src/Core/Materials/OOShaderProgram.m +++ b/src/Core/Materials/OOShaderProgram.m @@ -414,7 +414,14 @@ static BOOL ValidateShaderObject(GLhandleARB object, NSString *name) if ([obj isKindOfClass:[NSArray class]]) { pair = (NSArray*)obj; - GLUniformMatrix([[pair objectAtIndex: 0] intValue], [matrixManager getMatrix: [[pair objectAtIndex: 1] intValue]]); + if ([[pair oo_stringAtIndex: 2] compare: @"mat3"] == 0) + { + GLUniformMatrix3([pair oo_intAtIndex: 0], [matrixManager getMatrix: [pair oo_intAtIndex: 1]]); + } + else + { + GLUniformMatrix([pair oo_intAtIndex: 0], [matrixManager getMatrix: [pair oo_intAtIndex: 1]]); + } } } } diff --git a/src/Core/OOMatrix.h b/src/Core/OOMatrix.h index 0e6d0908..f0901f76 100644 --- a/src/Core/OOMatrix.h +++ b/src/Core/OOMatrix.h @@ -106,6 +106,7 @@ OOMatrix OOMatrixOrthogonalize(OOMatrix m) CONST_FUNC; #define GLMultTransposeOOMatrix(M) do { OOMatrix m_ = M; OOGL(glMultTransposeMatrixf(OOMatrixValuesForOpenGL(m_))); } while (0) #define GLLoadTransposeOOMatrix(M) do { OOMatrix m_ = M; OOGL(glLoadTransposeMatrixf(OOMatrixValuesForOpenGL(m_))); } while (0) #define GLUniformMatrix(location, M) do { OOGL(glUniformMatrix4fvARB(location, 1, NO, OOMatrixValuesForOpenGL(M))); } while (0) +void GLUniformMatrix3(GLint location, OOMatrix M); OOINLINE OOMatrix OOMatrixLoadGLMatrix(GLenum matrixID) ALWAYS_INLINE_FUNC; #endif @@ -135,14 +136,16 @@ void OOMatrixColumnOperation(OOMatrix *M, int column1, OOScalar factor1, int col // Transforms between square matrices -// return matrix X such that XA = B, or zero matrix if X doesn't exist +// return matrix X such that XA = B, or zero matrix if X doesn't exist. OOMatrix OOMatrixLeftTransform(OOMatrix A, OOMatrix B); -// return matrix X such that AX = B, or zero matrix if X doesn't exist +// return matrix X such that AX = B, or zero matrix if X doesn't exist. OOMatrix OOMatrixRightTransform(OOMatrix A, OOMatrix B); // Matrix inversion OOMatrix OOMatrixInverse(OOMatrix M); +// Inverts matrix returning determinant of inverse in +OOMatrix OOMatrixInverseWithDeterminant(OOMatrix M, OOScalar *determinant); /*** Only inline definitions beyond this point ***/ diff --git a/src/Core/OOMatrix.m b/src/Core/OOMatrix.m index 608cb834..afbad6df 100644 --- a/src/Core/OOMatrix.m +++ b/src/Core/OOMatrix.m @@ -393,3 +393,77 @@ OOMatrix OOMatrixInverse(OOMatrix M) return OOMatrixLeftTransform(M, kIdentityMatrix); } +OOMatrix OOMatrixInverseWithDeterminant(OOMatrix M, OOScalar *d) +{ + int i, j; + OOMatrix B = kIdentityMatrix; + BOOL found; + + *d = 1.0; + for (i = 0; i < 4; i++) + { + if (M.m[i][i] == 0.0) + { + found = NO; + for (j = i+1; j < 4; j++) + { + if (M.m[j][i] != 0.0) + { + found = YES; + OOMatrixRowSwap(&M,i,j); + OOMatrixRowSwap(&B,i,j); + *d *= -1; + break; + } + } + if (!found) + { + *d = 0.0; + return kZeroMatrix; + } + } + *d /= M.m[i][i]; + OOMatrixRowScale(&B, i, 1/M.m[i][i]); + OOMatrixRowScale(&M, i, 1/M.m[i][i]); + for (j = i+1; j < 4; j++) + { + if (M.m[j][i] != 0.0) + { + OOMatrixRowOperation(&B, j, 1, i, -M.m[j][i]); + OOMatrixRowOperation(&M, j, 1, i, -M.m[j][i]); + } + } + } + for (i = 3; i > 0; i--) + { + for (j = 0; j < i; j++) + { + if (M.m[j][i] != 0.0) + { + OOMatrixRowOperation(&B, j, 1, i, -M.m[j][i]); + OOMatrixRowOperation(&M, j, 1, i, -M.m[j][i]); + } + } + } + return B; +} + +#if OOMATHS_OPENGL_INTEGRATION + +void GLUniformMatrix3(int location, OOMatrix M) +{ + OOScalar m[9]; + m[0] = M.m[0][0]; + m[1] = M.m[0][1]; + m[2] = M.m[0][2]; + m[3] = M.m[1][0]; + m[4] = M.m[1][1]; + m[5] = M.m[1][2]; + m[6] = M.m[2][0]; + m[7] = M.m[2][1]; + m[8] = M.m[2][2]; + OOGL(glUniformMatrix3fvARB(location, 1, NO, m)); +} + +#endif + diff --git a/src/Core/OOOpenGLMatrixManager.m b/src/Core/OOOpenGLMatrixManager.m index f4a36d0d..37c9e740 100644 --- a/src/Core/OOOpenGLMatrixManager.m +++ b/src/Core/OOOpenGLMatrixManager.m @@ -351,6 +351,7 @@ static OOOpenGLMatrixManager * sharedMatrixManager = nil; { if (which < 0 || which >= OOLITE_GL_MATRIX_END) return kIdentityMatrix; if (valid[which]) return matrices[which]; + OOScalar d; switch(which) { case OOLITE_GL_MATRIX_MODELVIEW_PROJECTION: @@ -365,7 +366,18 @@ static OOOpenGLMatrixManager * sharedMatrixManager = nil; matrices[which].m[1][3] = 0.0; matrices[which].m[2][3] = 0.0; matrices[which].m[3][3] = 1.0; - matrices[which] = OOMatrixTranspose(OOMatrixInverse(matrices[which])); + matrices[which] = OOMatrixTranspose(OOMatrixInverseWithDeterminant(matrices[which], &d)); + if (d != 0.0) + { + d = pow(fabs(d), 1.0/3); + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + matrices[which].m[i][j] /= d; + } + } + } break; case OOLITE_GL_MATRIX_MODELVIEW_INVERSE: matrices[which] = OOMatrixInverse(matrices[OOLITE_GL_MATRIX_MODELVIEW]); @@ -402,17 +414,30 @@ static OOOpenGLMatrixManager * sharedMatrixManager = nil; - (NSArray*) standardMatrixUniformLocations: (GLuint) program { GLint location; - int i; + NSUInteger i; NSMutableArray *locationSet = [[[NSMutableArray alloc] init] autorelease]; for (i = 0; i < OOLITE_GL_MATRIX_END; i++) { location = glGetUniformLocationARB(program, ooliteStandardMatrixUniforms[i]); if (location >= 0) { - [locationSet addObject: - [NSArray arrayWithObjects: - [NSNumber numberWithInt: location], - [NSNumber numberWithInt: i], - nil]]; + if (i == OOLITE_GL_MATRIX_NORMAL) + { + [locationSet addObject: + [NSArray arrayWithObjects: + [NSNumber numberWithInt: location], + [NSNumber numberWithInt: i], + @"mat3", + nil]]; + } + else + { + [locationSet addObject: + [NSArray arrayWithObjects: + [NSNumber numberWithInt: location], + [NSNumber numberWithInt: i], + @"mat4", + nil]]; + } } } return [[NSArray arrayWithArray: locationSet] retain];