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);
  } 
}
Example #3
0
// 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);
  }
}