bool CCharShape::RotateNode (size_t node_name, int axis, double angle) { TCharNode *node = GetNode (node_name); if (node == NULL) return false; if (axis > 3) return false; TMatrix rotMatrix; char caxis = '0'; switch (axis) { case 1: caxis = 'x'; break; case 2: caxis = 'y'; break; case 3: caxis = 'z'; break; } MakeRotationMatrix (rotMatrix, angle, caxis); MultiplyMatrices (node->trans, node->trans, rotMatrix); MakeRotationMatrix (rotMatrix, -angle, caxis); MultiplyMatrices (node->invtrans, rotMatrix, node->invtrans); if (newActions && useActions) AddAction (node_name, axis, NullVec, angle); return true; }
void MultiplyRotationMatrices (TMatrix mat, TMatrix inv, double angle, char axis) { if(mat) { TMatrix r; MakeRotationMatrix( r, angle, axis ); MultiplyMatrices( mat, mat, r ); } if(inv) { TMatrix ir; MakeRotationMatrix( ir, -angle, axis ); MultiplyMatrices( inv, ir, inv ); } }
void RotateAboutVectorMatrix (TMatrix mat, TVector3 u, double angle) { TMatrix rx, irx, ry, iry; double a, b, c, d; a = u.x; b = u.y; c = u.z; d = sqrt (b*b + c*c); if (d < EPS) { if (a < 0) MakeRotationMatrix (mat, -angle, 'x'); else MakeRotationMatrix (mat, angle, 'x'); return; } MakeIdentityMatrix (rx); MakeIdentityMatrix (irx); MakeIdentityMatrix (ry); MakeIdentityMatrix (iry); rx[1][1] = c/d; rx[2][1] = -b/d; rx[1][2] = b/d; rx[2][2] = c/d; irx[1][1] = c/d; irx[2][1] = b/d; irx[1][2] = -b/d; irx[2][2] = c/d; ry[0][0] = d; ry[2][0] = -a; ry[0][2] = a; ry[2][2] = d; iry[0][0] = d; iry[2][0] = a; iry[0][2] = -a; iry[2][2] = d; MakeRotationMatrix (mat, angle, 'z'); MultiplyMatrices (mat, mat, ry); MultiplyMatrices (mat, mat, rx); MultiplyMatrices (mat, iry, mat); MultiplyMatrices (mat, irx, mat); }
void RotateAboutVectorMatrix (TMatrix mat, TVector3 u, double angle) { TMatrix rx, irx, ry, iry; double a, b, c, d, bd, cd; a = u.x; b = u.y; c = u.z; d = sqrt (b*b + c*c); if (d < EPS) { angle = (a < 0 ? -angle : angle); MakeRotationMatrix (mat, angle, 'x'); return; } MakeRotationMatrix (mat, angle, 'z'); bd = b/d; cd = c/d; //MakeIdentityMatrix (ry); ry[0][0] = d; ry[0][1] = 0.0; ry[0][2] = a; ry[0][3] = 0.0; ry[1][0] = 0.0; ry[1][1] = 1.0; ry[1][2] = 0.0; ry[1][3] = 0.0; ry[2][0] = -a; ry[2][1] = 0.0; ry[2][2] = d; ry[2][3] = 0.0; ry[3][0] = 0.0; ry[3][1] = 0.0; ry[3][2] = 0.0; ry[3][3] = 1.0; MultiplyMatrices (mat, mat, ry); //MakeIdentityMatrix (rx); rx[0][0] = 1.0; rx[0][1] = 0.0; rx[0][2] = 0.0; rx[0][3] = 0.0; rx[1][0] = 0.0; rx[1][1] = cd; rx[1][2] = bd; rx[1][3] = 0.0; rx[2][0] = 0.0; rx[2][1] = -bd; rx[2][2] = cd; rx[2][3] = 0.0; rx[3][0] = 0.0; rx[3][1] = 0.0; rx[3][2] = 0.0; rx[3][3] = 1.0; MultiplyMatrices (mat, mat, rx); //MakeIdentityMatrix (iry); iry[0][0] = d; iry[0][1] = 0.0; iry[0][2] = -a; iry[0][3] = 0.0; iry[1][0] = 0.0; iry[1][1] = 1.0; iry[1][2] = 0.0; iry[1][3] = 0.0; iry[2][0] = a; iry[2][1] = 0.0; iry[2][2] = d; iry[2][3] = 0.0; iry[3][0] = 0.0; iry[3][1] = 0.0; iry[3][2] = 0.0; iry[3][3] = 1.0; MultiplyMatrices (mat, iry, mat); //MakeIdentityMatrix (irx); irx[0][0] = 1.0; irx[0][1] = 0.0; irx[0][2] = 0.0; irx[0][3] = 0.0; irx[1][0] = 0.0; irx[1][1] = cd; irx[1][2] = -bd; irx[1][3] = 0.0; irx[2][0] = 0.0; irx[2][1] = bd; irx[2][2] = cd; irx[2][3] = 0.0; irx[3][0] = 0.0; irx[3][1] = 0.0; irx[3][2] = 0.0; irx[3][3] = 1.0; MultiplyMatrices (mat, irx, mat); }
/* * Create direction vector from angles in 3D (ignoring banking). */ void AnglesToDirectionVector(const ANGLE3D &a3dAngles, FLOAT3D &vDirection) { // find the rotation matrix from the angles FLOATmatrix3D mDirection; MakeRotationMatrix(mDirection, a3dAngles); // rotate a front oriented vector by the matrix vDirection = FLOAT3D(0.0f, 0.0f, -1.0f)*mDirection; }
// mirror a placement of one entity static void MirrorAndStretchPlacement(CPlacement3D &pl) { ASSERT(_wmtMirror==WMT_X||_wmtMirror==WMT_Y||_wmtMirror==WMT_Z||_wmtMirror==WMT_NONE); // if there should be mirror if (_wmtMirror!=WMT_NONE) { // make rotation matrix for the placement FLOATmatrix3D m; MakeRotationMatrix(m, pl.pl_OrientationAngle); // get row vectors, with object x flipped FLOAT3D vX(-m(1,1),m(1,2),m(1,3)); FLOAT3D vY(-m(2,1),m(2,2),m(2,3)); FLOAT3D vZ(-m(3,1),m(3,2),m(3,3)); // flip needed axis switch(_wmtMirror) { case WMT_X: pl.pl_PositionVector(1) = -pl.pl_PositionVector(1); vX = -vX; break; case WMT_Y: pl.pl_PositionVector(2) = -pl.pl_PositionVector(2); vY = -vY; break; case WMT_Z: pl.pl_PositionVector(3) = -pl.pl_PositionVector(3); vZ = -vZ; break; default: ASSERT(FALSE); } // compose matrix back from the vectors m(1,1) = vX(1); m(2,1) = vY(1); m(3,1) = vZ(1); m(1,2) = vX(2); m(2,2) = vY(2); m(3,2) = vZ(2); m(1,3) = vX(3); m(2,3) = vY(3); m(3,3) = vZ(3); // decompose matrix into angles DecomposeRotationMatrix(pl.pl_OrientationAngle, m); } pl.pl_PositionVector*=_fStretch; }
/*********************************************************************** ComputeInitLink() - this function computes the initial end points, u,v,n vectors, and rotation matrix for the specified link. for the given link set visible end to origin + vislen set actual end to origin + totlen rotate both points by theta about z axis translate both points to actual end of previous link compute u,v,n vectors map end points to screen coordinates ***********************************************************************/ int ComputeInitLink(int link, MyProgram *data) { vectorType o2, o2prime, o3, o3prime; vectorType p1, p2, p3; vectorType u, v, vprime, n; double world[4]; double screen[4]; matrixType translation; matrixType rotation; matrixType screen_map; pointType MapWPointToScreen(wpointType *p, matrixType *map); /* set actual end to origin + totlen */ o3.x = data->links[link].total_length; o3.y = 0.0; o3.z = 0.0; /* set visible end to origin + vislen */ o2.x = data->links[link].visible_length; o2.y = 0.0; o2.z = 0.0; /* make rotation matrix */ rotation = MakeRotationMatrix('z', data->links[link].zrot_deg); MatrixCopy(&rotation, &data->links[link].rot_mat); /* rotate actual and visible end points around z axis */ o3prime = TransformVector(&o3, &rotation); /* o3prime = o3 * Rz(theta) */ o2prime = TransformVector(&o2, &rotation); /* o2prime = o2 * Rz(theta) */ /* set start of link to actual end of previous link if not root link */ if (data->links[link].type == LINK_ROOT) { /* root link */ p1.x = data->links[link].w_start.x; p1.y = data->links[link].w_start.y; p1.z = data->links[link].w_start.z; } else { /* normal link */ p1.x = data->links[link - 1].w_end.x; p1.y = data->links[link - 1].w_end.y; p1.z = data->links[link - 1].w_end.z; } /* make translation matrix */ translation = MakeTranslationMatrix(p1.x, p1.y, p1.z); /* translate actual end and visible end to final locations */ p3 = TransformVector(&o3prime, &translation); /* p3 = o3prime * T(ox,oy,oz) */ p2 = TransformVector(&o2prime, &translation); /* p2 = o2prime * T(ox,oy,oz) */ /* copy final end locations to link data */ data->links[link].w_end.x = p3.x; /* actual end */ data->links[link].w_end.y = p3.y; data->links[link].w_end.z = p3.z; data->links[link].w_visend.x = p2.x; /* visible end */ data->links[link].w_visend.y = p2.y; data->links[link].w_visend.z = p2.z; data->links[link].w_start.x = p1.x; /* start point */ data->links[link].w_start.y = p1.y; data->links[link].w_start.z = p1.z; /* compute u vector */ u = VecSub(&p1, &p3); /* u = p3 - p1 */ VecNormalize(&u); /* u = u / mag(u) */ /* compute n vector */ vprime.x = 0.0; vprime.y = 1.0; vprime.z = 0.0; n = VecCrossproduct(&u, &vprime); /* n = u X vprime */ /* compute v vector */ v = VecCrossproduct(&n, &u); /* v = n X u */ /* copy u,v,n vectors to link data */ data->links[link].u_vec.x = u.x; data->links[link].u_vec.y = u.y; data->links[link].u_vec.z = u.z; data->links[link].v_vec.x = v.x; data->links[link].v_vec.y = v.y; data->links[link].v_vec.z = v.z; data->links[link].n_vec.x = n.x; data->links[link].n_vec.y = n.y; data->links[link].n_vec.z = n.z; /* map start and end points to screen coordinates */ world[0] = WB_MINX; world[1] = WB_MINY; world[2] = WB_MAXX; world[3] = WB_MAXY; screen[0] = 0.0; screen[1] = 0.0; screen[2] = SCREEN_X_SIZE; screen[3] = SCREEN_Y_SIZE; screen_map = MakeMappingMatrix(world, screen); data->links[link].start = MapWPointToScreen( &data->links[link].w_start, &screen_map); data->links[link].end = MapWPointToScreen( &data->links[link].w_end, &screen_map); data->links[link].visend = MapWPointToScreen( &data->links[link].w_visend, &screen_map); #ifdef INVKINE_DEBUG OutputLink(stdout, data, link); #endif return(0); } /* end of ComputeInitLink() */
/* * Prepare for projecting. */ void CParallelProjection3D::Prepare(void) { FLOATmatrix3D t3dObjectStretch; // matrix for object stretch FLOATmatrix3D t3dObjectRotation; // matrix for object angles // calc. matrices for viewer and object angles and stretch MakeRotationMatrix(t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); // object normally MakeInverseRotationMatrix(pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); // viewer inverse t3dObjectStretch.Diagonal(pr_ObjectStretch); pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; BOOL bXInverted = pr_ObjectStretch(1)<0; BOOL bYInverted = pr_ObjectStretch(2)<0; BOOL bZInverted = pr_ObjectStretch(3)<0; pr_bInverted = (bXInverted != bYInverted) != bZInverted; // if the projection is mirrored if (pr_bMirror) { // reflect viewer ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); // invert inversion pr_bInverted = !pr_bInverted; } // calculate screen center pr_ScreenCenter = pr_ScreenBBox.Center(); // if the object is face-forward if (pr_bFaceForward) { // apply object stretch only pr_RotationMatrix = t3dObjectStretch; } else { // first apply object stretch then object rotation and then viewer rotation pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; } // calc. offset of object from viewer pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; // rotate offset only by viewer angles pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; // transform handle from object space to viewer space and add it to the offset pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate pr_fDepthBufferFactor = -pr_NearClipDistance; pr_fDepthBufferMul = (pr_fDepthBufferFar-pr_fDepthBufferNear); pr_fDepthBufferAdd = pr_fDepthBufferNear; // make clip planes MakeClipPlane(FLOAT3D(+pr_vZoomFactors(1),0,+pr_vStepFactors(1)), pr_ScreenBBox.Min()(1)-pr_ScreenCenter(1), pr_plClipL); MakeClipPlane(FLOAT3D(-pr_vZoomFactors(1),0,-pr_vStepFactors(1)), pr_ScreenCenter(1)-pr_ScreenBBox.Max()(1), pr_plClipR); MakeClipPlane(FLOAT3D(0,-pr_vZoomFactors(2),-pr_vStepFactors(2)), pr_ScreenBBox.Min()(2)-pr_ScreenCenter(2), pr_plClipU); MakeClipPlane(FLOAT3D(0,+pr_vZoomFactors(2),+pr_vStepFactors(2)), pr_ScreenCenter(2)-pr_ScreenBBox.Max()(2), pr_plClipD); // find vector in direction of viewing pr_vViewDirection = FLOAT3D( pr_vStepFactors(1)/pr_vZoomFactors(1), pr_vStepFactors(2)/pr_vZoomFactors(2), -1.0f); // mark as prepared pr_Prepared = TRUE; }
void CCharShape::RefreshNode (size_t idx) { if (idx >= numNodes) return; TMatrix TempMatrix; char caxis; double angle; TCharNode *node = Nodes[idx]; TCharAction *act = node->action; if (act == NULL) return; if (act->num < 1) return; MakeIdentityMatrix (node->trans); MakeIdentityMatrix (node->invtrans); for (size_t i=0; i<act->num; i++) { int type = act->type[i]; const TVector3& vec = act->vec[i]; double dval = act->dval[i]; switch (type) { case 0: MakeTranslationMatrix (TempMatrix, vec.x, vec.y, vec.z); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeTranslationMatrix (TempMatrix, -vec.x, -vec.y, -vec.z); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); break; case 1: caxis = 'x'; angle = dval; MakeRotationMatrix (TempMatrix, angle, caxis); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeRotationMatrix (TempMatrix, -angle, caxis); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); break; case 2: caxis = 'y'; angle = dval; MakeRotationMatrix (TempMatrix, angle, caxis); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeRotationMatrix (TempMatrix, -angle, caxis); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); break; case 3: caxis = 'z'; angle = dval; MakeRotationMatrix (TempMatrix, angle, caxis); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeRotationMatrix (TempMatrix, -angle, caxis); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); break; case 4: MakeIdentityMatrix (TempMatrix); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeIdentityMatrix (TempMatrix); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); MakeScalingMatrix (TempMatrix, vec.x, vec.y, vec.z); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeScalingMatrix (TempMatrix, 1.0 / vec.x, 1.0 / vec.y, 1.0 / vec.z); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); MakeIdentityMatrix (TempMatrix); MultiplyMatrices (node->trans, node->trans, TempMatrix); MakeIdentityMatrix (TempMatrix); MultiplyMatrices (node->invtrans, TempMatrix, node->invtrans); break; case 5: VisibleNode (node->node_name, dval); break; default: break; } } }