// Draw one quad tree node ( draws terrain tile in wireframe mode if leaf node )
static void DrawWireQuadTreeNode(INDEX iqtn)
{
  ASSERT(_ptrTerrain!=NULL);
  CEntity *pen = _ptrTerrain->tr_penEntity;
  QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[iqtn];
  
  FLOATmatrix3D &mAbsToView = _aprProjection->pr_ViewerRotationMatrix;
  FLOATobbox3D obbox = FLOATobbox3D( qtn.qtn_aabbox, 
    (pen->en_plPlacement.pl_PositionVector-_aprProjection->pr_vViewerPosition)*mAbsToView, mAbsToView*pen->en_mRotation);

  INDEX iFrustumTest = _aprProjection->TestBoxToFrustum(obbox);
  if(iFrustumTest!=(-1)) {
    // is this leaf node
    if(qtn.qtn_iTileIndex != -1) {
      _ctNodesVis++;
      // draw terrain tile for this node 
      RenderWireTile(qtn.qtn_iTileIndex);
    // this node has some children
    } else {
      for(INDEX iqc=0;iqc<4;iqc++) {
        INDEX iChildNode = qtn.qtn_iChild[iqc];
        // if child node exists
        if(iChildNode != -1) {
          // draw child node
          DrawWireQuadTreeNode(qtn.qtn_iChild[iqc]);
        }
      }
    }
  }
}
Exemple #2
0
// Create render model structure for rendering an attached model
BOOL CModelObject::CreateAttachment( CRenderModel &rmMain, CAttachmentModelObject &amo)
{
  _pfModelProfile.StartTimer( CModelProfile::PTI_CREATEATTACHMENT);
  _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_CREATEATTACHMENT);
  CRenderModel &rmAttached = *amo.amo_prm;
  rmAttached.rm_ulFlags = rmMain.rm_ulFlags&(RMF_FOG|RMF_HAZE|RMF_WEAPON) | RMF_ATTACHMENT;

  // get the position
  rmMain.rm_pmdModelData->md_aampAttachedPosition.Lock();
  const CAttachedModelPosition &amp = rmMain.rm_pmdModelData->md_aampAttachedPosition[amo.amo_iAttachedPosition];
  rmMain.rm_pmdModelData->md_aampAttachedPosition.Unlock();

  // copy common values
  rmAttached.rm_vLightDirection = rmMain.rm_vLightDirection;
  rmAttached.rm_fDistanceFactor = rmMain.rm_fDistanceFactor;
  rmAttached.rm_colLight   = rmMain.rm_colLight;
  rmAttached.rm_colAmbient = rmMain.rm_colAmbient;
  rmAttached.rm_colBlend   = rmMain.rm_colBlend;

  // unpack the reference vertices
  FLOAT3D vCenter, vFront, vUp;
  const INDEX iCenter = amp.amp_iCenterVertex;
  const INDEX iFront  = amp.amp_iFrontVertex;
  const INDEX iUp     = amp.amp_iUpVertex;
  UnpackVertex( rmMain, iCenter, vCenter);
  UnpackVertex( rmMain, iFront,  vFront);
  UnpackVertex( rmMain, iUp,     vUp);

  // create front and up direction vectors
  FLOAT3D vY = vUp - vCenter;
  FLOAT3D vZ = vCenter - vFront;
  // project center and directions from object to absolute space
  const FLOATmatrix3D &mO2A = rmMain.rm_mObjectRotation;
  const FLOAT3D &vO2A = rmMain.rm_vObjectPosition;
  vCenter = vCenter*mO2A +vO2A;
  vY = vY *mO2A;
  vZ = vZ *mO2A;

  // make a rotation matrix from the direction vectors
  FLOAT3D vX = vY*vZ;
  vY = vZ*vX;
  vX.Normalize();
  vY.Normalize();
  vZ.Normalize();
  FLOATmatrix3D mOrientation;
  mOrientation(1,1) = vX(1);  mOrientation(1,2) = vY(1);  mOrientation(1,3) = vZ(1);
  mOrientation(2,1) = vX(2);  mOrientation(2,2) = vY(2);  mOrientation(2,3) = vZ(2);
  mOrientation(3,1) = vX(3);  mOrientation(3,2) = vY(3);  mOrientation(3,3) = vZ(3);

  // adjust for relative placement of the attachment
  FLOAT3D vOffset;
  FLOATmatrix3D mRelative;
  MakeRotationMatrixFast( mRelative, amo.amo_plRelative.pl_OrientationAngle);
  vOffset(1) = amo.amo_plRelative.pl_PositionVector(1) * mo_Stretch(1);
  vOffset(2) = amo.amo_plRelative.pl_PositionVector(2) * mo_Stretch(2);
  vOffset(3) = amo.amo_plRelative.pl_PositionVector(3) * mo_Stretch(3);
  FLOAT3D vO = vCenter + vOffset * mOrientation;
  mOrientation *= mRelative; // convert absolute to relative orientation
  rmAttached.SetObjectPlacement( vO, mOrientation);

  // done here if clipping optimizations are not allowed
  extern INDEX gap_iOptimizeClipping;
  if( gap_iOptimizeClipping<1) { 
    gap_iOptimizeClipping = 0;
    _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT);
    return TRUE;
  }

  // test attachment to frustum and/or mirror
  FLOAT3D vHandle;
  _aprProjection->PreClip( vO, vHandle);
  CalculateBoundingBox( &amo.amo_moModelObject, rmAttached);

  // compose view-space bounding box and sphere of an attacment
  const FLOAT fR = Max( rmAttached.rm_vObjectMinBB.Length(), rmAttached.rm_vObjectMaxBB.Length());
  const FLOATobbox3D boxEntity( FLOATaabbox3D(rmAttached.rm_vObjectMinBB, rmAttached.rm_vObjectMaxBB),
                                vHandle, _aprProjection->pr_ViewerRotationMatrix*mOrientation);
  // frustum test?
  if( gap_iOptimizeClipping>1) {
    // test sphere against frustrum
    INDEX iFrustumTest = _aprProjection->TestSphereToFrustum(vHandle,fR);
    if( iFrustumTest==0) {
      // test box if sphere cut one of frustum planes
      iFrustumTest = _aprProjection->TestBoxToFrustum(boxEntity);
    }
    // mark if attachment is fully inside frustum
         if( iFrustumTest>0) rmAttached.rm_ulFlags |= RMF_INSIDE; 
    else if( iFrustumTest<0) { // if completely outside of frustum
      // signal skip rendering only if doesn't have any attachments
      _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT);
      return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); 
    }
  }
  // test sphere against mirror/warp plane (if any)
  if( _aprProjection->pr_bMirror || _aprProjection->pr_bWarp) {
    INDEX iMirrorPlaneTest;
    const FLOAT fPlaneDistance = _aprProjection->pr_plMirrorView.PointDistance(vHandle);
         if( fPlaneDistance < -fR) iMirrorPlaneTest = -1;
    else if( fPlaneDistance > +fR) iMirrorPlaneTest = +1;
    else { // test box if sphere cut mirror plane
      iMirrorPlaneTest = boxEntity.TestAgainstPlane(_aprProjection->pr_plMirrorView);
    }
    // mark if attachment is fully inside mirror
         if( iMirrorPlaneTest>0) rmAttached.rm_ulFlags |= RMF_INMIRROR; 
    else if( iMirrorPlaneTest<0) { // if completely outside mirror
      // signal skip rendering only if doesn't have any attachments
      _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT);
      return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); 
    }
  } 
  // all done
  _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT);
  return TRUE;
}