/* * Ray++ - Object-oriented ray tracing library * Copyright (C) 1998-2001 Martin Reinecke and others. * See the AUTHORS file for more information. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * See the README file for more information. */ #include "kernel/transform.h" #include "kernel/constants.h" #include "kernel/error.h" namespace RAYPP { TRANSMAT:: TRANSMAT (float4 a00, float4 a01, float4 a02, float4 a10, float4 a11, float4 a12, float4 a20, float4 a21, float4 a22, float4 a30, float4 a31, float4 a32) { entry[0][0] = a00; entry[1][0] = a01; entry[2][0] = a02; entry[0][1] = a10; entry[1][1] = a11; entry[2][1] = a12; entry[0][2] = a20; entry[1][2] = a21; entry[2][2] = a22; entry[0][3] = a30; entry[1][3] = a31; entry[2][3] = a32; } TRANSMAT &TRANSMAT::operator*= (const TRANSMAT &b) { TRANSMAT a(*this); int i,j; for (i = 0 ; i < 4 ; ++i) for (j = 0 ; j < 3 ; ++j) entry[j][i] = a.entry[0][i] * b.entry[j][0] + a.entry[1][i] * b.entry[j][1] + a.entry[2][i] * b.entry[j][2]; entry[0][3] += b.entry[0][3]; entry[1][3] += b.entry[1][3]; entry[2][3] += b.entry[2][3]; return *this; } TRANSMAT &TRANSMAT::operator+= (const TRANSMAT &b) { for (int i = 0 ; i < 12 ; ++i) p[i] += b.p[i]; return *this; } TRANSMAT &TRANSMAT::operator-= (const TRANSMAT &b) { for (int i = 0 ; i < 12 ; ++i) p[i] -= b.p[i]; return *this; } TRANSMAT &TRANSMAT::operator*= (float8 factor) { for (int i = 0 ; i < 12 ; ++i) p[i] *= factor; return *this; } TRANSMAT TRANSMAT::Inverse () const { TRANSMAT tmp; float8 d; tmp.entry[0][0] = entry[1][1]*entry[2][2] - entry[2][1]*entry[1][2]; tmp.entry[0][1] = entry[0][1]*entry[2][2] - entry[2][1]*entry[0][2]; tmp.entry[0][2] = entry[0][1]*entry[1][2] - entry[1][1]*entry[0][2]; tmp.entry[1][0] = entry[1][0]*entry[2][2] - entry[2][0]*entry[1][2]; tmp.entry[1][1] = entry[0][0]*entry[2][2] - entry[2][0]*entry[0][2]; tmp.entry[1][2] = entry[0][0]*entry[1][2] - entry[1][0]*entry[0][2]; tmp.entry[2][0] = entry[1][0]*entry[2][1] - entry[2][0]*entry[1][1]; tmp.entry[2][1] = entry[0][0]*entry[2][1] - entry[2][0]*entry[0][1]; tmp.entry[2][2] = entry[0][0]*entry[1][1] - entry[1][0]*entry[0][1]; d = 1.0 / (entry[0][0]*tmp.entry[0][0] - entry[1][0]*tmp.entry[0][1] + entry[2][0]*tmp.entry[0][2]); if (abs(d) > Huge_float4) error ("degenerate matrix in TRANSMAT::Inverse()"); tmp.entry[0][0] *= d; tmp.entry[2][0] *= d; tmp.entry[1][1] *= d; tmp.entry[0][2] *= d; tmp.entry[2][2] *= d; d = -d; tmp.entry[1][0] *= d; tmp.entry[0][1] *= d; tmp.entry[2][1] *= d; tmp.entry[1][2] *= d; tmp.entry[0][3] = - (tmp.entry[0][0]*entry[0][3] + tmp.entry[0][1]*entry[1][3] + tmp.entry[0][2]*entry[2][3]); tmp.entry[1][3] = - (tmp.entry[1][0]*entry[0][3] + tmp.entry[1][1]*entry[1][3] + tmp.entry[1][2]*entry[2][3]); tmp.entry[2][3] = - (tmp.entry[2][0]*entry[0][3] + tmp.entry[2][1]*entry[1][3] + tmp.entry[2][2]*entry[2][3]); return tmp; } void TRANSMAT::Invert () { *this = Inverse(); } void TRANSMAT::SetToIdentity () { for (int m=0; m<12; ++m) p[m]=0; entry[0][0]=entry[1][1]=entry[2][2]=1; } void TRANSMAT::SetToZero () { for (int m=0; m<12; ++m) p[m]=0; } void TRANSMAT::Transpose () { swap(entry[0][1], entry[1][0]); swap(entry[0][2], entry[2][0]); swap(entry[1][2], entry[2][1]); entry[0][3] = entry [1][3] = entry[2][3] = 0.0; } bool TRANSMAT::Orthogonal () const { if (abs (entry[0][0]*entry[1][0] + entry[0][1]*entry[1][1] + entry[0][2]*entry[1][2]) > Small_float4) return false; if (abs (entry[0][0]*entry[2][0] + entry[0][1]*entry[2][1] + entry[0][2]*entry[2][2]) > Small_float4) return false; if (abs (entry[2][0]*entry[1][0] + entry[2][1]*entry[1][1] + entry[2][2]*entry[1][2]) > Small_float4) return false; return true; } bool TRANSMAT::Orthonormal () const { if (!Orthogonal()) return false; if (abs (entry[0][0]*entry[0][0] + entry[0][1]*entry[0][1] + entry[0][2]*entry[0][2] - 1.0) > Small_float4) return false; if (abs (entry[1][0]*entry[1][0] + entry[1][1]*entry[1][1] + entry[1][2]*entry[1][2] - 1.0) > Small_float4) return false; if (abs (entry[2][0]*entry[2][0] + entry[2][1]*entry[2][1] + entry[2][2]*entry[2][2] - 1.0) > Small_float4) return false; return true; } bool TRANSMAT::Scaled_Orthonormal (float8 &factor) const { if (!Orthogonal()) return false; factor = entry[0][0]*entry[0][0] + entry[0][1]*entry[0][1] + entry[0][2]*entry[0][2]; if (abs (entry[1][0]*entry[1][0] + entry[1][1]*entry[1][1] + entry[1][2]*entry[1][2] - factor) > Small_float4) return false; if (abs (entry[2][0]*entry[2][0] + entry[2][1]*entry[2][1] + entry[2][2]*entry[2][2] - factor) > Small_float4) return false; factor = sqrt (factor); return true; } bool TRANSMAT::Diagonal () const { if ((abs (entry[1][0]) > Small_float4) || (abs (entry[2][0]) > Small_float4) || (abs (entry[2][1]) > Small_float4) || (abs (entry[0][1]) > Small_float4) || (abs (entry[0][2]) > Small_float4) || (abs (entry[1][2]) > Small_float4)) return false; return true; } ostream &operator<< (ostream &os, const TRANSMAT &mat) { for (int i=0;i<4;++i) os << mat.entry[i][0] << ' ' << mat.entry[i][1] << ' ' << mat.entry[i][2] << endl; return os; } void TRANSFORM::Make_Scaling_Transform (const VECTOR &vec) { if ((vec.x