////////////////////////////////////////////////////////////////////// // // Pixie // // Copyright © 1999 - 2003, Okan Arikan // // Contact: okan@cs.berkeley.edu // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU 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 // General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // // File : xform.cpp // Classes : CXform // Description : Implementation // //////////////////////////////////////////////////////////////////////// #include #include #include "xform.h" #include "error.h" #include "stats.h" /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : CXform // Description : Constructor // Return Value : - // Comments : Identity at the beginning // Date last edited : 3/3/2001 CXform::CXform() { stats.numXforms++; stats.xformMemory += sizeof(CXform); next = NULL; refCount = 0; identitym(from); identitym(to); flip = 0; } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : CXform // Description : Create an exact copy of another xform // Return Value : - // Comments : // Date last edited : 3/3/2001 CXform::CXform(CXform *a) { stats.numXforms++; stats.xformMemory += sizeof(CXform); if (a->next != NULL) next = new CXform(a->next); else next = NULL; refCount = 0; movmm(from,a->from); movmm(to,a->to); flip = a->flip; } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : ~CXform // Description : Destructor // Return Value : - // Comments : // Date last edited : 3/3/2001 CXform::~CXform() { stats.numXforms--; stats.xformMemory -= sizeof(CXform); if (next != NULL) delete next; } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : identity // Description : Initialize the transformation to identity // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::identity() { identitym(from); identitym(to); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : translate // Description : Append a translation. Note that the last // specified transformation is applied first // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::translate(float dx,float dy,float dz) { matrix tmp,tmp2; translatem(tmp,-dx,-dy,-dz); mulmm(tmp2,tmp,to); movmm(to,tmp2); translatem(tmp,dx,dy,dz); mulmm(tmp2,from,tmp); movmm(from,tmp2); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : rotate // Description : Append a rotation // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::rotate(float angle,float x,float y,float z) { matrix tmp,tmp2; rotatem(tmp,-x,-y,-z,angle); mulmm(tmp2,tmp,to); movmm(to,tmp2); rotatem(tmp,x,y,z,angle); mulmm(tmp2,from,tmp); movmm(from,tmp2); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : scale // Description : Append a scale // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::scale(float sx,float sy,float sz) { matrix tmp,tmp2; if ((sx == 0) || (sy == 0) || (sz == 0)) error(CODE_MATH,"Singular scale (%f %f %f) (ignored)\n",sx,sy,sz); else { scalem(tmp,1/sx,1/sy,1/sz); mulmm(tmp2,tmp,to); movmm(to,tmp2); scalem(tmp,sx,sy,sz); mulmm(tmp2,from,tmp); movmm(from,tmp2); } } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : skew // Description : Append a skew // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::skew(float angle,float dx1,float dy1,float dz1,float dx2,float dy2,float dz2) { matrix tmp,tmp2; skewm(tmp,-angle,dx1,dy1,dz1,dx2,dy2,dz2); mulmm(tmp2,tmp,to); movmm(to,tmp2); skewm(tmp,angle,dx1,dy1,dz1,dx2,dy2,dz2); mulmm(tmp2,from,tmp); movmm(from,tmp2); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : concat // Description : Concetenate another transformation (This // transformation will be applied first) // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::concat(CXform *x) { matrix tmp; if (x->next != NULL) { if (next == NULL) next = new CXform(this); next->concat(x->next); } mulmm(tmp,x->to,to); movmm(to,tmp); mulmm(tmp,from,x->from); movmm(from,tmp); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : invert // Description : Invert the transformation // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::invert() { matrix tmp; movmm(tmp,from); movmm(from,to); movmm(to,tmp); } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : transformBound // Description : Transfer the bounding box from one system to another // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::transformBound(float *bmin,float *bmax) const { vector corners[8]; int i; const float *from; vector vtmp; from = this->from; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); movvv(bmin,corners[0]); movvv(bmax,corners[0]); for (i=1;i<8;i++) { addBox(bmin,bmax,corners[i]); } if (next != NULL) { from = next->from; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); for (i=0;i<8;i++) { addBox(bmin,bmax,corners[i]); } } } /////////////////////////////////////////////////////////////////////// // Class : CXform // Method : invTransformBound // Description : Transfer the bounding box from one system to another // Return Value : - // Comments : // Date last edited : 3/3/2001 void CXform::invTransformBound(float *bmin,float *bmax) const { vector corners[8]; int i; const float *from; vector vtmp; from = this->to; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); movvv(bmin,corners[0]); movvv(bmax,corners[0]); for (i=1;i<8;i++) { addBox(bmin,bmax,corners[i]); } if (next != NULL) { from = next->from; // Compute & transfer the corners to the dest space initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[0],from,vtmp); initv(vtmp,bmin[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[1],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[2],from,vtmp); initv(vtmp,bmin[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[3],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmin[COMP_Z]); mulmp(corners[4],from,vtmp); initv(vtmp,bmax[COMP_X],bmin[COMP_Y],bmax[COMP_Z]); mulmp(corners[5],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmax[COMP_Z]); mulmp(corners[6],from,vtmp); initv(vtmp,bmax[COMP_X],bmax[COMP_Y],bmin[COMP_Z]); mulmp(corners[7],from,vtmp); for (i=0;i<8;i++) { addBox(bmin,bmax,corners[i]); } } }