void CCastRay::TestModelSimple(CEntity *penModel, CModelObject &mo) { // get model's bounding box for current frame FLOATaabbox3D boxModel; mo.GetCurrentFrameBBox(boxModel); boxModel.StretchByVector(mo.mo_Stretch); // get center and radius of the bounding sphere in absolute space FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; FLOAT3D vSphereCenter = boxModel.Center(); vSphereCenter*=penModel->en_mRotation; vSphereCenter+=penModel->en_plPlacement.pl_PositionVector; // if the ray doesn't hit the sphere FLOAT fSphereHitDistance; if (!RayHitsSphere(cr_vOrigin, cr_vTarget, vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { // ignore return; } // if the ray hits the sphere closer than closest found hit point yet if (fSphereHitDistance<cr_fHitDistance && fSphereHitDistance>0.0f) { // set the current entity as new hit target cr_fHitDistance=fSphereHitDistance; cr_penHit = penModel; cr_pbscBrushSector = NULL; cr_pbpoBrushPolygon = NULL; } }
// TEMP - Draw one AABBox void gfxDrawWireBox(FLOATaabbox3D &bbox, COLOR col) { FLOAT3D vMinVtx = bbox.Min(); FLOAT3D vMaxVtx = bbox.Max(); // fill vertex array so it represents bounding box FLOAT3D vBoxVtxs[8]; vBoxVtxs[0] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMinVtx(3)); vBoxVtxs[1] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMinVtx(3)); vBoxVtxs[2] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMaxVtx(3)); vBoxVtxs[3] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMaxVtx(3)); vBoxVtxs[4] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMinVtx(3)); vBoxVtxs[5] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMinVtx(3)); vBoxVtxs[6] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMaxVtx(3)); vBoxVtxs[7] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMaxVtx(3)); // connect vertices into lines of bounding box INDEX iBoxLines[12][2]; iBoxLines[ 0][0] = 0; iBoxLines[ 0][1] = 1; iBoxLines[ 1][0] = 1; iBoxLines[ 1][1] = 2; iBoxLines[ 2][0] = 2; iBoxLines[ 2][1] = 3; iBoxLines[ 3][0] = 3; iBoxLines[ 3][1] = 0; iBoxLines[ 4][0] = 0; iBoxLines[ 4][1] = 4; iBoxLines[ 5][0] = 1; iBoxLines[ 5][1] = 5; iBoxLines[ 6][0] = 2; iBoxLines[ 6][1] = 6; iBoxLines[ 7][0] = 3; iBoxLines[ 7][1] = 7; iBoxLines[ 8][0] = 4; iBoxLines[ 8][1] = 5; iBoxLines[ 9][0] = 5; iBoxLines[ 9][1] = 6; iBoxLines[10][0] = 6; iBoxLines[10][1] = 7; iBoxLines[11][0] = 7; iBoxLines[11][1] = 4; // for all vertices in bounding box for( INDEX i=0; i<12; i++) { // get starting and ending vertices of one line FLOAT3D &v0 = vBoxVtxs[iBoxLines[i][0]]; FLOAT3D &v1 = vBoxVtxs[iBoxLines[i][1]]; _pdp->DrawLine3D(v0,v1,col); } }
// Recalculate all frames bounding box for current model void CDlgClient::OnBtCalcAllframesBbox() { CSeriousSkaStudioDoc *pDoc = theApp.GetDocument(); CModelInstance *pmi = pmiSelected; if(pmi == NULL) return; FLOATaabbox3D bbox; // AnimQueue aqOld = pmi->mi_aqAnims; ClearAnimQueue(*pmi); pmi->NewClearState(0.0f); bbox = AddAllVerticesToBBox(*pmi); // for each animset in model instance INDEX ctas = pmi->mi_aAnimSet.Count(); for(INDEX ias=0;ias<ctas;ias++) { CAnimSet &as = pmi->mi_aAnimSet[ias]; // for each animation in animset INDEX ctan = as.as_Anims.Count(); for(INDEX ian=0;ian<ctan;ian++) { Animation &an = as.as_Anims[ian]; AnimQueue &aq = pmi->mi_aqAnims; FLOAT fSecPerFrame = an.an_fSecPerFrame; INDEX ctFrames = an.an_iFrames; ClearAnimQueue(*pmi); pmi->NewClearState(0.0f); pmi->AddAnimation(an.an_iID,AN_NOGROUP_SORT,1,0); ASSERT(aq.aq_Lists.Count()==1); FLOAT fNow = aq.aq_Lists[0].al_fStartTime - fSecPerFrame*ctFrames; // for each frame in animation for(INDEX ifr=0;ifr<ctFrames;ifr++) { AnimList &an = aq.aq_Lists[0]; ASSERT(an.al_PlayedAnims.Count()==1); PlayedAnim &pa = an.al_PlayedAnims[0]; an.al_fStartTime=fNow; pa.pa_fStartTime=fNow; fNow+=fSecPerFrame; bbox |= AddAllVerticesToBBox(*pmi); } } } pmi->NewClearState(0.0f); ClearAnimQueue(*pmi); // pmi->mi_aqAnims = aqOld; // Set bbox in model instance FLOAT3D vMin = bbox.Min(); FLOAT3D vMax = bbox.Max(); pmi->mi_cbAllFramesBBox.SetMin(vMin); pmi->mi_cbAllFramesBBox.SetMax(vMax); theApp.ReselectCurrentItem(); pDoc->MarkAsChanged(); theApp.NotificationMessage("All frames bounding box recalculated."); }
void CDlgPgCollision::OnAllignToSize() { CModelerView *pModelerView = CModelerView::GetActiveView(); if(pModelerView == NULL) return; CModelerDoc* pDoc = pModelerView->GetDocument(); FLOATaabbox3D MaxBB; pDoc->m_emEditModel.edm_md.GetAllFramesBBox( MaxBB); pDoc->m_emEditModel.SetCollisionBox( MaxBB.Min(), MaxBB.Max()); UpdateData(FALSE); pDoc->SetModifiedFlag(); pDoc->UpdateAllViews( NULL); }
static FLOATaabbox3D CalculateAABBoxFromRect(CTerrain *ptrTerrain, Rect rcExtract) { ASSERT(ptrTerrain!=NULL); ASSERT(ptrTerrain->tr_penEntity!=NULL); // Get entity that holds this terrain //CEntity *penEntity = ptrTerrain->tr_penEntity; FLOATaabbox3D bboxExtract; FLOATaabbox3D bboxAllTerrain; ptrTerrain->GetAllTerrainBBox(bboxAllTerrain); FLOAT fMinY = bboxAllTerrain.minvect(2); FLOAT fMaxY = bboxAllTerrain.maxvect(2); bboxExtract.minvect = FLOAT3D(rcExtract.rc_iLeft * ptrTerrain->tr_vStretch(1),fMinY,rcExtract.rc_iTop * ptrTerrain->tr_vStretch(3)); bboxExtract.maxvect = FLOAT3D(rcExtract.rc_iRight * ptrTerrain->tr_vStretch(1),fMaxY,rcExtract.rc_iBottom * ptrTerrain->tr_vStretch(3)); return bboxExtract; }
// check if given bounding box is selected by lasso BOOL IsBoundingBoxInLasso( CProjection3D &prProjection, const FLOATaabbox3D &box, FLOATmatrix3D *pmR, FLOAT3D &vOffset) { FLOAT3D vMin = box.Min(); FLOAT3D vMax = box.Max(); // test lasso influence for all of bounding box's vertices if( IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMin(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMax(3)), pmR, vOffset) && IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMax(3)), pmR, vOffset) ) { return TRUE; } return FALSE; }
void ShowSelectionInternal(CTerrain *ptrTerrain, Rect &rcExtract, CTextureData *ptdBrush, GFXColor colSelection, FLOAT fStrenght, SelectionFill sfFill) { ASSERT(ptrTerrain!=NULL); ASSERT(ptdBrush!=NULL); Rect rcSelection; FLOATaabbox3D bboxSelection; // Clamp rect used for extraction rcSelection.rc_iLeft = Clamp(rcExtract.rc_iLeft , 0, ptrTerrain->tr_pixHeightMapWidth); rcSelection.rc_iTop = Clamp(rcExtract.rc_iTop , 0, ptrTerrain->tr_pixHeightMapHeight); rcSelection.rc_iRight = Clamp(rcExtract.rc_iRight , 0, ptrTerrain->tr_pixHeightMapWidth); rcSelection.rc_iBottom = Clamp(rcExtract.rc_iBottom , 0, ptrTerrain->tr_pixHeightMapHeight); // Prepare box for vertex selection bboxSelection = FLOAT3D(rcSelection.rc_iLeft, 0, rcSelection.rc_iTop); bboxSelection |= FLOAT3D(rcSelection.rc_iRight, 0, rcSelection.rc_iBottom); // Stretch selection box bboxSelection.minvect(1) *= ptrTerrain->tr_vStretch(1); bboxSelection.minvect(3) *= ptrTerrain->tr_vStretch(3); bboxSelection.maxvect(1) *= ptrTerrain->tr_vStretch(1); bboxSelection.maxvect(3) *= ptrTerrain->tr_vStretch(3); // Set selection box height FLOATaabbox3D bboxAllTerrain; ptrTerrain->GetAllTerrainBBox(bboxAllTerrain); bboxSelection.minvect(2) = bboxAllTerrain.minvect(2); bboxSelection.maxvect(2) = bboxAllTerrain.maxvect(2); GFXVertex *pavVertices; INDEX *paiIndices; INDEX ctVertices; INDEX ctIndices; // Extract vertices in selection rect ExtractVerticesInRect(ptrTerrain, rcSelection, &pavVertices, &paiIndices, ctVertices, ctIndices); if(ctVertices!=rcSelection.Width()*rcSelection.Height()) { ASSERT(FALSE); return; } // if no vertices if(ctVertices==0) { return; } // Prepare vertex colors for selection preview PIX pixWidth = rcSelection.Width(); PIX pixHeight = rcSelection.Height(); INDEX iStepX = ptdBrush->GetWidth() - pixWidth; INDEX iFirst = 0; if(rcExtract.rc_iTop<0) { iFirst += -rcExtract.rc_iTop*ptdBrush->GetWidth(); } if(rcExtract.rc_iLeft<0) { iFirst += -rcExtract.rc_iLeft; } _aiExtColors.Push(ctVertices); GFXColor *pacolColor = (GFXColor*)&_aiExtColors[0]; GFXColor *pacolBrush = (GFXColor*)&ptdBrush->td_pulFrames[iFirst]; // Fill vertex colors for selection preview SLONG slStrength = (SLONG) (Clamp(Abs(fStrenght),0.0f,1.0f) * 256.0f); // for each row for(INDEX iy=0;iy<pixHeight;iy++) { // for each col for(INDEX ix=0;ix<pixWidth;ix++) { pacolColor->ul.abgr = colSelection.ul.abgr; pacolColor->ub.a = (pacolBrush->ub.r*slStrength)>>8; pacolColor++; pacolBrush++; } pacolBrush+=iStepX; } // Render selected polygons for selection preview if(sfFill == SF_WIREFRAME) { gfxPolygonMode(GFX_LINE); gfxEnableDepthBias(); } if(sfFill != SF_POINTS) { // Draw selection gfxDisableTexture(); gfxDisableAlphaTest(); gfxEnableBlend(); gfxBlendFunc(GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); gfxSetVertexArray(pavVertices,ctVertices); gfxSetColorArray(&_aiExtColors[0]); gfxLockArrays(); gfxDrawElements(ctIndices,paiIndices); gfxUnlockArrays(); gfxDisableBlend(); } if(sfFill == SF_WIREFRAME) { gfxDisableDepthBias(); gfxPolygonMode(GFX_FILL); } if(sfFill == SF_POINTS) { DrawSelectedVertices(pavVertices,&_aiExtColors[0],ctVertices); } }
void CDlgPgCollision::DoDataExchange(CDataExchange* pDX) { CModelerView *pModelerView = CModelerView::GetActiveView(); if(pModelerView == NULL) return; CModelerDoc* pDoc = pModelerView->GetDocument(); // if transfering data from document to dialog if( !pDX->m_bSaveAndValidate) { // get collision min vector FLOAT3D vMinCollisionBox = pDoc->m_emEditModel.GetCollisionBoxMin(); // get collision max vector FLOAT3D vMaxCollisionBox = pDoc->m_emEditModel.GetCollisionBoxMax(); FLOATaabbox3D bboxCollision = FLOATaabbox3D( vMinCollisionBox, vMaxCollisionBox); m_fWidth = bboxCollision.Size()(1); m_fHeight = bboxCollision.Size()(2); m_fLenght = bboxCollision.Size()(3); m_fXCenter = bboxCollision.Center()(1); m_fYDown = vMinCollisionBox(2); m_fZCenter = bboxCollision.Center()(3); // set equality radio initial value INDEX iEqualityType = pDoc->m_emEditModel.GetCollisionBoxDimensionEquality(); // get index of curently selected collision box char achrString[ 256]; sprintf( achrString, "%d.", pDoc->m_emEditModel.GetActiveCollisionBoxIndex()); m_strCollisionBoxIndex = achrString; // get name of curently selected collision box sprintf( achrString, "%s", pDoc->m_emEditModel.GetCollisionBoxName()); m_strCollisionBoxName = achrString; // enable all controls GetDlgItem( IDC_STATIC_WIDTH)->EnableWindow( TRUE); GetDlgItem( IDC_EDIT_WIDTH)->EnableWindow( TRUE); GetDlgItem( IDC_STATIC_HEIGHT)->EnableWindow( TRUE); GetDlgItem( IDC_EDIT_HEIGHT)->EnableWindow( TRUE); GetDlgItem( IDC_STATIC_LENGHT)->EnableWindow( TRUE); GetDlgItem( IDC_EDIT_LENGHT)->EnableWindow( TRUE); m_bCollideAsBox = pDoc->m_emEditModel.edm_md.md_bCollideAsCube; // if we are colliding using sphere approximation switch( iEqualityType) { case HEIGHT_EQ_WIDTH: { m_EqualityRadio = 0; if( !m_bCollideAsBox) { GetDlgItem( IDC_STATIC_HEIGHT)->EnableWindow( FALSE); GetDlgItem( IDC_EDIT_HEIGHT)->EnableWindow( FALSE); m_fHeight = m_fWidth; } break; } case LENGTH_EQ_WIDTH: { m_EqualityRadio = 1; if( !m_bCollideAsBox) { GetDlgItem( IDC_STATIC_LENGHT)->EnableWindow( FALSE); GetDlgItem( IDC_EDIT_LENGHT)->EnableWindow( FALSE); m_fLenght = m_fWidth; } break; } case LENGTH_EQ_HEIGHT: { m_EqualityRadio = 2; if( !m_bCollideAsBox) { GetDlgItem( IDC_STATIC_LENGHT)->EnableWindow( FALSE); GetDlgItem( IDC_EDIT_LENGHT)->EnableWindow( FALSE); m_fLenght = m_fHeight; } break; } default: { ASSERTALWAYS( "None of collision dimensions are the same and that can't be."); } } // mark that the values have been updated to reflect the state of the view m_udAllValues.MarkUpdated(); } CPropertyPage::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDlgPgCollision) DDX_SkyFloat(pDX, IDC_EDIT_WIDTH, m_fWidth); DDX_SkyFloat(pDX, IDC_EDIT_HEIGHT, m_fHeight); DDX_SkyFloat(pDX, IDC_EDIT_LENGHT, m_fLenght); DDX_SkyFloat(pDX, IDC_EDIT_XCENTER, m_fXCenter); DDX_SkyFloat(pDX, IDC_EDIT_YDOWN, m_fYDown); DDX_SkyFloat(pDX, IDC_EDIT_ZCENTER, m_fZCenter); DDX_Radio(pDX, IDC_H_EQ_W, m_EqualityRadio); DDX_Text(pDX, IDC_COLLISION_BOX_NAME, m_strCollisionBoxName); DDX_Text(pDX, IDC_COLLISION_BOX_INDEX, m_strCollisionBoxIndex); DDX_Check(pDX, IDC_COLLIDE_AS_BOX, m_bCollideAsBox); //}}AFX_DATA_MAP // if transfering data from dialog to document if( pDX->m_bSaveAndValidate) { // if we are colliding using sphere approximation if( !pDoc->m_emEditModel.edm_md.md_bCollideAsCube) { INDEX iEqualityType; switch( m_EqualityRadio) { case 0: { iEqualityType = HEIGHT_EQ_WIDTH; CString strWidth; GetDlgItem( IDC_EDIT_WIDTH)->GetWindowText(strWidth); GetDlgItem( IDC_EDIT_HEIGHT)->SetWindowText(strWidth); break; } case 1: { iEqualityType = LENGTH_EQ_WIDTH; CString strWidth; GetDlgItem( IDC_EDIT_WIDTH)->GetWindowText(strWidth); GetDlgItem( IDC_EDIT_LENGHT)->SetWindowText( strWidth ); break; } case 2: { iEqualityType = LENGTH_EQ_HEIGHT; CString strHeight; GetDlgItem( IDC_EDIT_HEIGHT)->GetWindowText(strHeight); GetDlgItem( IDC_EDIT_LENGHT)->SetWindowText( strHeight); break; } default: { ASSERTALWAYS( "Illegal value found in collision dimensions equality radio."); } } // set collision equality value if( pDoc->m_emEditModel.GetCollisionBoxDimensionEquality() != iEqualityType) { pDoc->m_emEditModel.SetCollisionBoxDimensionEquality( iEqualityType); } } // set name of curently selected collision box pDoc->m_emEditModel.SetCollisionBoxName( CTString( m_strCollisionBoxName) ); // get collision min and max vectors FLOAT3D vMinCollisionBox; FLOAT3D vMaxCollisionBox; // get sizing values vMinCollisionBox(1) = m_fXCenter-m_fWidth/2.0f; vMinCollisionBox(2) = m_fYDown; vMinCollisionBox(3) = m_fZCenter-m_fLenght/2.0f; // get origin coordinates vMaxCollisionBox(1) = m_fXCenter+m_fWidth/2.0f; vMaxCollisionBox(2) = m_fYDown+m_fHeight; vMaxCollisionBox(3) = m_fZCenter+m_fLenght/2.0f; // transfer data from dialog to document pDoc->m_emEditModel.SetCollisionBox( vMinCollisionBox, vMaxCollisionBox); pDoc->SetModifiedFlag(); // update all views pDoc->UpdateAllViews( NULL); } }