www.pudn.com > MeshProcess.rar > Transform.cpp


/*________________________________________________ 
 |                                           
 |  跟踪球算法 
 |________________________________________________*/ 
 
#include "stdafx.h" 
#include "Transform.h" 
#include  
#include  
#include  
 
 
//---------------- vector & matrix operation ----------------------- 
 
// V = ( x, y, z ) 
void VectorCopy(VECTOR & V, float x, float y, float z) 
{ 
   V.x = x; 
   V.y = y; 
   V.z = z; 
} 
 
// V = A  
void VectorCopy(VECTOR & V, VECTOR A) 
{ 
   V.x = A.x; 
   V.y = A.y; 
   V.z = A.z; 
} 
 
// V = A + B 
void VectorAdd(VECTOR & V, VECTOR A, VECTOR B) 
{ 
  V.x = A.x + B.x; 
  V.y = A.y + B.y; 
  V.z = A.z + B.z; 
} 
 
// V = A - B 
void VectorSub(VECTOR & V, VECTOR A, VECTOR B) 
{ 
  V.x = A.x - B.x; 
  V.y = A.y - B.y; 
  V.z = A.z - B.z; 
} 
 
// V = s * V 
void VectorScale(VECTOR & V, float s) 
{ 
   V.x = s * V.x; 
   V.y = s * V.y; 
   V.z = s * V.z; 
} 
 
// V = A x B 
void VectorCross(VECTOR & V, VECTOR A, VECTOR B) 
{ 
  V.x = A.y*B.z - A.z*B.y; 
  V.y = A.z*B.x - A.x*B.z; 
  V.z = A.x*B.y - A.y*B.x; 
} 
 
// dot = A . B 
void VectorDot(float & dot, VECTOR A, VECTOR B) 
{ 
  dot = A.x*B.x + A.y*B.y + A.z*B.z; 
} 
 
// len = |V| 
void VectorLength(float & len, VECTOR V) 
{ 
   len = sqrt(V.x*V.x + V.y*V.y + V.z*V.z); 
} 
 
// V = V/(|V|) 
void VectorNormalize(VECTOR & V) 
{ 
  float len; 
 
  len = sqrt(V.x*V.x + V.y*V.y + V.z*V.z); 
 
  if(len<=0.0000001f) 
    { 
	  V.x = 0.0f; 
	  V.y = 0.0f; 
	  V.z = 0.0f; 
    } 
  else 
    { 
	  V.x /= len; 
	  V.y /= len; 
	  V.z /= len; 
    } 
} 
 
// M = M1 * M2 
void MultMatrixf( float *M,  float *M1, float *M2, 
					 int m1Row, int m1Col, int m2Row, int m2Col) 
{ 
  if ( m1Col != m2Row )  return ; 
  int size = m1Row * m2Col; 
   
  for( int i=0, i1=0; i big)  big = temp; 
        
	if( big == 0.0f ) 
    { 
      delete vv; 
	  return 0; 
    } 
      
	vv[i] = 1.0f /big; 
  } 
  for( j = 0, jj = 0; j < n; j++, jj += n) 
  { 
     for( i = 0, ii = 0; i <= j; i++, ii += n) 
     { 
       temp = data[ii+j]; 
       for( int k = 0, kk = 0; k < i; k++, kk += n) 
	       temp -= data[ii+k] * data[kk+j]; 
       data[ii+j] = temp; 
     } 
     big = 0.0f; 
     imax = j; 
     for ( i = j+1, ii = i * n; i < n; i++, ii += n) 
     { 
	   temp = data[ii+j]; 
	   for( k = 0, kk = 0; k < j; k++, kk += n) 
	      temp -= data[ii+k] * data[kk+j]; 
	   data[ii+j] = temp; 
	   if(( temp = vv[i] * fabs(temp)) > big) 
	   { 
	     big = temp; 
	     imax = i; 
        } 
     } 
     if( j != imax) 
     { 
	   ii = imax * n; 
	   for ( k = 0; k < n; k++) 
	   { 
	   temp = data[ii+k]; 
	   data[ii+k] = data[jj+k]; 
	   data[jj+k] = temp; 
	   } 
	   vv[imax] = vv[j]; 
     } 
     index[j] = imax; 
     if( data[jj+j] == 0.0f ) data[jj+j] = TINY; 
     if( j < n) 
     { 
	   temp = 1.0f/data[jj+j]; 
	   for ( i = j+1, ii = i * n; i < n; i++, ii += n) 
	   data[ii+j] *= temp; 
     } 
   } 
   delete vv; 
   return 1; 
} 
 
void LUBksb( float *data, int *index, float *b, int n) 
{ 
  int ii, i, j, k = -1, ip; 
  float sum; 
  for ( i = 0, ii = 0; i < n; i++, ii += n) 
  { 
    ip = index[i]; 
    sum = b[ip]; 
    b[ip] = b[i]; 
    if ( k != -1) 
      for ( j = k; j < i; j++)    sum -= data[ii+j]*b[j]; 
    else if ( sum) 
      k = i; 
    b[i] = sum; 
  } 
  for( i = n-1, ii = i * n; i >=0; i--, ii -= n) 
  { 
    sum = b[i]; 
    for( j = i + 1; j < n; j++)   sum -= data[ii+j] * b[j]; 
    b[i] = sum / data[ii+i]; 
  } 
} 
 
int InvMatrixf(float *data, int n) 
{ 
  int *index = new int [n]; 
  if ( LUDcmp( data, index, n) == 0) 
  { 
     delete index; 
     return 0; 
  } 
  float *b = new float [n]; 
  float *inva = new float [n*n]; 
  for ( int i = 0; i < n; i++) 
  { 
    for( int j = 0; j < n; j++)   b[j] = 0.0f; 
 
    b[i] = 1.0f; 
    LUBksb( data, index, b, n); 
    int jj; 
    for ( j = 0, jj = 0; j < n; j++, jj += n)   inva[jj+i] = b[j]; 
  } 
  for ( i = 0; i < n*n; i++)   data[i] = inva[i]; 
  delete b; 
  delete inva; 
  delete index; 
  return 1; 
} 
 
// transpose matrix 
void TransMatrix( float *M, int m, int n) 
{ 
   float *temp = new float [m*n]; 
   for( int i = 0, ii = 0; i < m; i++, ii += m) 
   { 
     for( int j = 0, jj = 0; j < n; j++, jj += n) 
        temp[ii+j] = M[jj+i]; 
   } 
 
   for( i = 0; i < m*n; i++)  M[i] = temp[i]; 
 
   delete temp; 
   return; 
} 
 
 
//------------------------------------------------------- 
// 跟踪球算法实现 
//------------------------------------------------------- 
// 参考 《科学计算可视化算法与系统》 P232 - P233 
//------------------------------------------------------- 
// 周昆,1998,3,23 
 
void Trackball(int   event,   float radius , 
				  float centerX, float centerY, float mouseX, float mouseY, 
				  float &axisX , float &axisY , float &axisZ, float &angle ) 
{ 
 
	//------ TB trackball ---- 
	static TrackballStruct TB; 
   
	if(event==0)  // TB_START 
	{ 
		TB.centerX = centerX;  
		TB.centerY = centerY;  
		TB.radius  = radius ; 
		TB.pointX1 = mouseX ;   // ! 
		TB.pointY1 = mouseY ;   // ! 
		return; 
	} 
	if(event>0)  // TB_MOVE , TB_END 
	{ 
		float sinTao, cosTao, sinOmiga, cosOmiga, sinSita, cosSita; 
 
		TB.centerX = centerX;  
		TB.centerY = centerY;  
		TB.radius  = radius ; 
		TB.pointX2 = mouseX ;   // ! 
		TB.pointY2 = mouseY ;   // ! 
 
		VECTOR  V1, V2, V3;  
		float len1, len2, len3; 
		float dot; 
		float dx,dy; 
 
		// 计算 sinTao, cosTao 
		dx = TB.pointX2 - TB.pointX1; 
		dy = TB.pointY2 - TB.pointY1; 
		VectorCopy(V1, dx, dy, 0.0f); 
   
		dx = TB.pointX1 - TB.centerX; 
		dy = TB.pointY1 - TB.centerY; 
		VectorCopy(V2, dx, dy, 0.0f); 
 
		VectorCross(V3, V2, V1); 
		VectorLength(len1, V1); 
		VectorLength(len2, V2); 
		VectorLength(len3, V3); 
   
		if( len1<=0.00001f  || len2<=0.00001f ) 
		{  
			sinTao = 0.0f; 
			cosTao = 1.0f; 
		}  
		else 
		{ 
			if( V3.z>=0.0f ) sinTao =  len3/(len1*len2); 
			else             sinTao = -len3/(len1*len2);  
			VectorDot(dot, V1, V2); 
			cosTao = dot/(len1*len2); 
		} 
 
		// 计算sinOmiga,cosOmiga 
		sinOmiga  = sqrt(dx*dx + dy*dy); 
		sinOmiga  = sinOmiga/TB.radius; 
		if(sinOmiga>1.0f) 
			sinOmiga=1.0; 
		//99/12/28 
		sinOmiga = 0.0f; 
		cosOmiga=sqrt(1.0-sinOmiga*sinOmiga); 
 
		//计算sinSita,cosSita 
		len1 = sqrt(dx*dx + dy*dy); 
		if(len1<=0.00001f) 
		{   
			sinSita = 0.0f; 
			cosSita = 1.0f; 
		} 
		else 
		{ 
			sinSita = dy/len1; 
			cosSita = dx/len1; 
		} 
 
		// 计算旋转角度,用《角度》表示 
		dx = TB.pointX2 - TB.pointX1; 
		dy = TB.pointY2 - TB.pointY1; 
		len1= sqrt(dx*dx + dy*dy); 
		angle = (len1/TB.radius)*45.0f; 
 
 
		TB.pointX1 = TB.pointX2; 
		TB.pointY1 = TB.pointY2; 
 
		float M [1][3] = { 0.0f,     0.0f,    0.0f      }; 
		float M0[1][3] = { 0.0f,     0.0f,    0.0f      }; 
		float M1[1][3] = {-sinTao,   cosTao,  0.0f      }; 
		float M2[3][3] = { cosOmiga, 0.0f,   -sinOmiga, 
							0.0f,     1.0f,   0.0f, 
							sinOmiga, 0.0f,   cosOmiga  }; 
		float M3[3][3] = { cosSita,  sinSita, 0.0f, 
							-sinSita,  cosSita, 0.0f, 
							0.0f,     0.0f,    1.0f      }; 
 
		MultMatrixf( &M0[0][0], &M1[0][0], &M2[0][0], 1, 3, 3, 3); 
		MultMatrixf( &M [0][0], &M0[0][0], &M3[0][0], 1, 3, 3, 3); 
 
		//----- output ----------- 
		axisX = M[0][0]; 
		axisY = M[0][1]; 
		axisZ = M[0][2]; 
	} // end of TB_MOVE  
} 
 
// transform point P(x,y,z) from object coordinate to world coordinate 
void ObjectToWorld(float point[3], float result[3]) 
{ 
	// (1) get current modelview matrix 
	float temp[4][4]; 
	glGetFloatv(GL_MODELVIEW_MATRIX, &temp[0][0]); 
 
	// (2) transpose the modelview matrix 
	TransMatrix( &temp[0][0], 4, 4); 
 
	float a[4][1]; 
	float b[4][1]; 
	a[0][0]=point[0]; 
	a[1][0]=point[1]; 
	a[2][0]=point[2]; 
	a[3][0]=1.0f ; 
     
	// (3) transform (x,y,z) from object coordinate to world coordinate     
    MultMatrixf( &b[0][0], &temp[0][0], &a[0][0], 4, 4, 4, 1); 
    result[0]=b[0][0]; 
    result[1]=b[1][0]; 
    result[2]=b[2][0]; 
} 
 
// transform point P(x,y,z) from world coordinate to object coordinate 
void WorldToObject(float point[3], float result[3]) 
{ 
  // (1) get current modelview matrix 
  float temp[4][4]; 
  glGetFloatv(GL_MODELVIEW_MATRIX, &temp[0][0]); 
 
  // (2) transpose the modelview matrix 
  TransMatrix( &temp[0][0], 4, 4); 
 
  // (3) inverse the modelview matrix 
  if( InvMatrixf(&temp[0][0], 4) ) 
  { 
	float a[4][1]; 
	float b[4][1]; 
	a[0][0]=point[0]; 
	a[1][0]=point[1]; 
	a[2][0]=point[2]; 
	a[3][0]=1.0f ; 
     
	// (4) transform (x,y,z) from world coordinate to object coordinate     
    MultMatrixf( &b[0][0], &temp[0][0], &a[0][0], 4, 4, 4, 1); 
    result[0]=b[0][0]; 
    result[1]=b[1][0]; 
    result[2]=b[2][0]; 
  } 
} 
 
// rotate in world coordinate 
void WorldRotate(float point[3], float normal[3], float angle) 
{ 
	float pp[3]; 
	float nn[3]; 
    float tt[3]; 
 
	float t[3]={0.0f,0.0f,0.0f}; 
	WorldToObject(point, pp); 
	WorldToObject(normal, nn); 
	WorldToObject(t, tt); 
	nn[0]-=tt[0]; 
	nn[1]-=tt[1]; 
	nn[2]-=tt[2]; 
	glTranslatef(pp[0],pp[1],pp[2]); 
	glRotatef(angle,nn[0],nn[1],nn[2]); 
	glTranslatef(-pp[0],-pp[1],-pp[2]); 
} 
 
// translate in world coordinate 
void WorldTranslate(float p[3]) 
{ 
  float pp[3]; 
  float tt[3]; 
 
  float t[3]={0.0f,0.0f,0.0f}; 
  WorldToObject(p, pp); 
  WorldToObject(t, tt); 
  pp[0]-=tt[0]; 
  pp[1]-=tt[1]; 
  pp[2]-=tt[2]; 
  glTranslatef(pp[0],pp[1],pp[2]); 
} 
 
// calculate eye axes vectors 
void SetEyeStruct(float eyeX,    float eyeY,    float eyeZ,  
					 float centerX, float centerY, float centerZ,  
					 float upX,     float upY,     float upZ, 
					 EYE  & eye) 
{ 
  eye.origin.x=eyeX; 
  eye.origin.y=eyeY; 
  eye.origin.z=eyeZ; 
  eye.center.x=centerX; 
  eye.center.y=centerY; 
  eye.center.z=centerZ; 
  eye.up.x=upX; 
  eye.up.y=upY; 
  eye.up.z=upZ; 
 
  // 计算眼睛各坐标轴的矢量 
  VECTOR v1,v2,v3; 
  VectorSub(v1,eye.center,eye.origin); 
  VectorNormalize(v1); 
  VectorCopy(v2,eye.up); 
  VectorCross(v3,v2,v1); 
  VectorNormalize(v3); 
  VectorCross(v2,v3,v1); 
  VectorCopy(eye.axisX,v3); 
  VectorCopy(eye.axisY,v2); 
  VectorCopy(eye.axisZ,v1); 
} 
 
// transform point P(x,y,z) from world coordinate to eye coordinate 
void WorldToEye(float point[3], float result[3], EYE eye) 
{ 
	float tmp[3][3]; 
	float a[3][1]; 
	float b[3][1]; 
 
	tmp[0][0]=(eye.axisX).x; 
	tmp[1][0]=(eye.axisX).y; 
	tmp[2][0]=(eye.axisX).z; 
	tmp[0][1]=(eye.axisY).x; 
	tmp[1][1]=(eye.axisY).y; 
	tmp[2][1]=(eye.axisY).z; 
	tmp[0][2]=(eye.axisZ).x; 
	tmp[1][2]=(eye.axisZ).y; 
	tmp[2][2]=(eye.axisZ).z; 
 
	InvMatrixf(&tmp[0][0],3); 
	a[0][0]=point[0]; 
	a[1][0]=point[1]; 
	a[2][0]=point[2]; 
	 
	MultMatrixf( &b[0][0], &tmp[0][0], &a[0][0], 3, 3, 3, 1); 
	result[0]=b[0][0]-eye.origin.x; 
	result[1]=b[1][0]-eye.origin.y; 
	result[2]=b[2][0]+eye.origin.z; 
} 
 
// transform point P(x,y,z) from eye coordinate to world coordinate 
void EyeToWorld(float point[3], float result[3], EYE eye) 
{ 
  VECTOR v1,v2,v3,v4,v5,v6; 
 
  VectorCopy(v1,eye.axisZ); 
  VectorCopy(v2,eye.axisY); 
  VectorCopy(v3,eye.axisX); 
  VectorScale(v3,point[0]); 
  VectorScale(v2,point[1]); 
  VectorScale(v1,point[2]); 
  VectorAdd(v4,v1,v2); 
  VectorAdd(v5,v4,v3); 
  VectorAdd(v6,eye.origin,v5); 
  result[0]=v6.x; 
  result[1]=v6.y; 
  result[2]=v6.z; 
} 
 
// rotate in eye coordinate 
void EyeRotate(float point[3], float normal[3], float angle,  
				  EYE eye) 
{ 
  float pp[3]; 
  float nn[3]; 
  float tt[3]; 
 
  float t[3]={0.0f,0.0f,0.0f}; 
  EyeToWorld(point, pp, eye); 
  EyeToWorld(normal, nn, eye); 
  EyeToWorld(t, tt, eye); 
  nn[0]-=tt[0]; 
  nn[1]-=tt[1]; 
  nn[2]-=tt[2]; 
  WorldRotate(pp, nn, angle); 
} 
 
// translate in eye coordinate 
void EyeTranslate(float p[3], EYE eye) 
{ 
  float pp[3]; 
  float tt[3]; 
 
  float t[3]={0.0f,0.0f,0.0f}; 
  EyeToWorld(p, pp, eye); 
  EyeToWorld(t, tt, eye); 
  pp[0]-=tt[0]; 
  pp[1]-=tt[1]; 
  pp[2]-=tt[2]; 
  WorldTranslate(pp); 
} 
 
 
void gluCube(CVer3D mver3d, double r) 
{ 
	glBegin(GL_POLYGON);				 
		glNormal3f(0,0,1); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z+r); 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z+r); 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z+r); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z+r);		 
	glEnd(); 
	glBegin(GL_POLYGON);				 
		glNormal3f(0,0,-1); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z-r); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z-r);		 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z-r);			 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z-r); 
	glEnd(); 
	glBegin(GL_POLYGON); 
		glNormal3f(1,0,0); 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z+r); 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z-r);		 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z-r);			 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z+r); 
	glEnd(); 
	glBegin(GL_POLYGON); 
		glNormal3f(-1,0,0); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z+r); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z+r); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z-r); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z-r);		 
	glEnd(); 
	glBegin(GL_POLYGON); 
		glNormal3f(0,1,0); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z+r); 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z+r);	 
		glVertex3f(mver3d.x+r,mver3d.y+r,mver3d.z-r); 
		glVertex3f(mver3d.x-r,mver3d.y+r,mver3d.z-r);		 
	glEnd(); 
	glBegin(GL_POLYGON); 
		glNormal3f(0,-1,0); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z+r); 
		glVertex3f(mver3d.x-r,mver3d.y-r,mver3d.z-r); 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z-r); 
		glVertex3f(mver3d.x+r,mver3d.y-r,mver3d.z+r); 
	glEnd(); 
}