BOOL CRVTrackerDrawPoly::OnRotate() { // Get the brush CEditBrush *pBrush = &m_pView->DrawingBrush(); // Make sure we've got at least three points specified if (pBrush->m_Points.GetSize() < 3) return FALSE; // The origin's point #1 CVector vOrigin = pBrush->m_Points[0]; // The original rotation direction's point #2 CVector vBase = pBrush->m_Points[1]; // The new rotation's point #3 CVector vNew = pBrush->m_Points[2]; // Get the base direction CVector vBaseDir = vBase - vOrigin; float fBaseMag = vBaseDir.Mag(); // Don't allow duplicate points if (fBaseMag < 0.01f) return TRUE; vBaseDir *= 1.0f / fBaseMag; // Get the rotation direction CVector vNewDir = vNew - vOrigin; float fNewMag = vNewDir.Mag(); // Don't allow duplicate points if (fNewMag < 0.01f) return TRUE; vNewDir *= 1.0f / fNewMag; // Get the rotation axis CVector vRotAxis = vNewDir.Cross(vBaseDir); // Get the sin of the angle from the cross product float fRotAngle = vRotAxis.Mag(); // Don't bother if the angle's 0... if (fRotAngle == 0.0f) return TRUE; // Normalize the axis vRotAxis *= 1.0f / fRotAngle; // Get the actual angle fRotAngle = (float)asin(fRotAngle); // Handle obtuse angles.. if (vBaseDir.Dot(vNewDir) < 0.0f) fRotAngle = MATH_PI - fRotAngle; LTMatrix mRotation; // Get the rotation matrix mRotation.SetupRot(vRotAxis, fRotAngle); // Set up an undo.. CEditRegion *pRegion = m_pView->GetRegion(); PreActionList actionList; for (uint32 nUndoLoop = 0; nUndoLoop < pRegion->m_Selections; ++nUndoLoop) actionList.AddTail(new CPreAction(ACTION_MODIFYNODE, pRegion->m_Selections[nUndoLoop])); m_pView->GetRegionDoc()->Modify(&actionList, TRUE); // If we're in geometry mode.. if (m_pView->GetEditMode() == GEOMETRY_EDITMODE) { // Get the selected vertices CVertRefArray vertList; m_pView->GetSelectedVerts(vertList); // Rotate 'em for (uint32 nVertLoop = 0; nVertLoop < vertList.GetSize(); ++nVertLoop) { CVertRef vert = vertList[nVertLoop]; if (!vert.IsValid()) continue; vert() -= vOrigin; mRotation.Apply(vert()); vert() += vOrigin; } } else { // Otherwise, rotate all the selected nodes for (uint32 nNodeLoop = 0; nNodeLoop < pRegion->m_Selections.GetSize( ); ++nNodeLoop) { pRegion->m_Selections[nNodeLoop]->Rotate(mRotation, vOrigin); } // Update the selection box since stuff rotated... m_pView->GetRegionDoc()->UpdateSelectionBox(); } return TRUE; }
// returns true if intersection happened, plus fills hit dist param with // the parametric position of the intersection on the ray dir. // the obb must be within ray-origin + ray-dir. So ray-dir isn't normalized. // source : Real-time rendering moller&haines inline bool i_OrientedBoundingBoxTest(const ModelOBB &mobb, const LTransform &tf, const LTVector &origin, const LTVector &dir, float &t) { float tmin = -999999999999.0f; float tmax = 999999999999.0f; LTVector vObbPos = mobb.m_Pos; // Setup our OBB's translated position LTMatrix obb_mat; obb_mat.Identity(); obb_mat.SetBasisVectors( &tf.m_Rot.Right(), &tf.m_Rot.Up(), &tf.m_Rot.Forward() ); obb_mat.SetTranslation( tf.m_Pos ); obb_mat.Apply(vObbPos); LTVector p = vObbPos - origin; float e ; float f; float hi; float t1,t2; // Setup OBB rotation tranforms LTMatrix mObbMat; mObbMat.SetBasisVectors(&mobb.m_Basis[0], &mobb.m_Basis[1], &mobb.m_Basis[2]); // Get matrix of our Node's rotation LTMatrix mTrMat; tf.m_Rot.ConvertToMatrix(mTrMat); // Apply our node rotation to our obb rotation mTrMat.Apply(mObbMat); // Get our translated basis vectors LTVector axis[3]; mObbMat.GetBasisVectors(&axis[0], &axis[1], &axis[2]); LTVector vSize = mobb.m_Size * 0.5f ; // we want the 1/2 size of the box. for( int i = 0 ; i < 3 ; i++ ) { e = axis[i].Dot(p); f = axis[i].Dot(dir); hi= vSize[i] ; // if( fabs(f) > 0.00015 ) { t1 = ( e + hi ) / f ; t2 = ( e - hi ) / f ; if( t1 > t2 ) {float v = t2 ; t2 = t1 ; t1 = v ; } if(t1 > tmin ) {tmin = t1 ;} if(t2 < tmax ) {tmax = t2 ;} if(tmin > tmax ) { return false ; } if(tmax < 0 ) { return false ; } } else if( ((-e - hi) > 0 ) || ( (-e + hi) < 0 )) { t = 0 ; return false ; } } if( tmin > 0 ) { t = tmin ; return true ; } else { t = tmax ; return true ;} }
static void RecurseAndGrowDims(CWorldNode *pNode, LTVector &vMin, LTVector &vMax, LTMatrix& mTransMat) { //sanity check if(pNode == NULL) { return; } // Grow the dims for this node switch (pNode->GetType()) { case Node_Object : { CBaseEditObj *pObject = pNode->AsObject(); LTVector vCenter; mTransMat.Apply(pObject->GetPos(), vCenter); //always include at least the object center VEC_MIN(vMin, vMin, vCenter); VEC_MAX(vMax, vMax, vCenter); #ifdef DIRECTEDITOR_BUILD //see if there are other dims we need for (uint32 nCurDim = pObject->GetNumDims(); nCurDim > 0; --nCurDim) { LTVector vDims = *pObject->GetDim(nCurDim - 1); LTVector vObjMin = vCenter - vDims; LTVector vObjMax = vCenter + vDims; VEC_MIN(vMin, vMin, vObjMin); VEC_MAX(vMax, vMax, vObjMax); } #endif } break; case Node_Brush: { CEditBrush *pBrush = pNode->AsBrush(); CBoundingBox BBox = pBrush->CalcBoundingBox(); //transform the bounding box LTVector vBoxMin, vBoxMax; mTransMat.Apply(BBox.m_Min, vBoxMin); mTransMat.Apply(BBox.m_Max, vBoxMax); VEC_MIN(vMin, vMin, vBoxMin); VEC_MAX(vMax, vMax, vBoxMax); } break; case Node_PrefabRef: { //create the new transformation matrix LTMatrix mRot; ::gr_SetupMatrixEuler(pNode->GetOr(), mRot.m); LTMatrix mTranslate; mTranslate.Identity(); mTranslate.SetTranslation(pNode->GetPos()); LTMatrix mNewTransMat = mTransMat * mTranslate * mRot; RecurseAndGrowDims((CWorldNode*)((CPrefabRef*)pNode)->GetPrefabTree(), vMin, vMax, mNewTransMat); } break; } // Go through the children GPOS iFinger = pNode->m_Children.GetHeadPosition(); while (iFinger) { CWorldNode *pChild = pNode->m_Children.GetNext(iFinger); RecurseAndGrowDims(pChild, vMin, vMax, mTransMat); } }