// 透視投影変換行列の確認
	__declspec(dllexport) void checkProjection(double srcPointX, double srcPointY, double srcPointZ, double& dstPointX, double& dstPointY, double* perspective)
    {
		cv::Mat perspectiveMat(3, 4, CV_64F, perspective);
		
		cv::Mat srcPoint(4, 1, CV_64F);
		cv::Mat dstPoint(3, 1, CV_64F);

		srcPoint.at<double>(0) = srcPointX;
		srcPoint.at<double>(1) = srcPointY;
		srcPoint.at<double>(2) = srcPointZ;
		srcPoint.at<double>(3) = 1;

		dstPoint = perspectiveMat * srcPoint;

		dstPointX = dstPoint.at<double>(0) / dstPoint.at<double>(2);
		dstPointY = dstPoint.at<double>(1) / dstPoint.at<double>(2);
	}
    //
    // RenderRallyPoint
    //
    // Display a rally point
    //
    static void RenderRallyPoint()
    {
      Point<S32> srcPoint(0, 0);
      Point<U32> dstPoint(0, 0);
      Matrix src, dst;

      // Get the single selected unit
      UnitObj *unit = data.cInfo.oneUnit.GetPointer();

      // Is there a rally point
      if (unit && unit->GetFootInstance() && unit->GetRallyPoint(dstPoint))
      {
        // Setup destination
        dst.ClearData();
        dst.posit.x = WorldCtrl::CellToMetresX(dstPoint.x);
        dst.posit.z = WorldCtrl::CellToMetresZ(dstPoint.z);
        dst.posit.y = TerrainData::FindFloorWithWater(dst.posit.x, dst.posit.z);

        // Find the source
        srcPoint.Set(S32(dstPoint.x), S32(dstPoint.z));
        unit->GetFootInstance()->ClampToFringe(srcPoint);
        src.ClearData();
        src.posit.x = WorldCtrl::CellToMetresX(srcPoint.x);
        src.posit.z = WorldCtrl::CellToMetresZ(srcPoint.z);
        src.posit.y = TerrainData::FindFloorWithWater(src.posit.x, src.posit.z);
      }
      else
      {
        // Act as if not selected
        unit = NULL;
      }

      if 
      (
        // Rally unit has been deselected
        (!unit && rallyUnitId) 
        
        || 
        
        (
          // Have a rally point unit
          unit 
          
          && 
          
          (
            // Different to last one
            (unit->Id() != rallyUnitId) 
            
            || 
            
            // Rally point location has changed
            (rallyUnitId && (dstPoint != rallyPoint))
          )
        )
      )
      {
        // Dispose of any current particle
        if (rallyParticle.Alive())
        {
          delete rallyParticle;
        }

        // Is there a unit selected
        if (unit)
        {
          // Never display a trail when same point
          if ((srcPoint.x != S32(dstPoint.x)) || (srcPoint.z != S32(dstPoint.z)))
          {
            // Create the runner particle
            if (ParticleClass *p = ParticleSystem::FindType(0x94E362BD)) // "Client::Rally"
            {
              Matrix m(src);
              m.posit.y += 3.0F;
			        Vector v(0.0f, 0.0f, 0.0f);
              rallyParticle = ParticleSystem::New(p, m, v, v, dst.posit - src.posit, 0.0F);
            }
          }

          // Remember this unit's info
          rallyUnitId = unit->Id();
          rallyPoint = dstPoint;
        }
        else
        {
          rallyUnitId = 0;
        }
      }

      // Render the start and end points
      if (unit)
      {     
        Common::Display::Mesh(0x693D5359, src, Color(0.0F, 0.8F, 0.0F, 0.7F)); // "Location"
        Common::Display::Mesh(0x693D5359, dst, Color(0.0F, 1.0F, 0.0F, 0.7F)); // "Location"
      }
    }
/*
 *  Draw the depth of field widget.
 */
void
DepthOfField::drawImage()
{
    const double focus = toImageCoordinate( focusDistance );
    const double near = toImageCoordinate( nearDistance );
    const double far = toImageCoordinate( farDistance );

    const QString focusString = toString( focusDistance );
    const QString nearString = toString( nearDistance );
    const QString farString = toString( farDistance );

    /*
     *  Construct the image:
     *  green and infocus for part that is within depth of field,
     *  gray and out of focus for part that is outside depth of field.
     */
    image = unfocusImage->copy();
    for( int row = 0; row < image.height(); row++ ) {
	unsigned int *rowData =
	    (unsigned int *)image.scanLine( row );
	unsigned int *rowDataFocus =
	    (unsigned int *)focusImage->scanLine( row );
	for( int col = near; col <= far; col++ ) {
	    rowData[col] = rowDataFocus[col];
	}
    }

    /*
     *  Set the tick marks and tick labels.
     */
    QPen pen;
    pen.setColor( Qt::darkGray );
    pen.setWidth( 1 );
    QPainter painter( &image );
    painter.initFrom( this );
    painter.setRenderHint( QPainter::Antialiasing, true );
    painter.setPen( pen );
    double factor;
    if(      units == UNITS_Feet   ) factor =  304.8;
    else if( units == UNITS_Metres ) factor = 1000.0;
    for( double l = 0.1; l <= 1000.0; l *= 10.0 ) {
	for( double d = l; d <= 10*l; d += l ) {
	    double x = toImageCoordinate( d * factor );
	    painter.drawLine( QLineF( x, vOffset+3, x, vOffset+7 ) );
	}
    }
    for( double l = 0.1; l <= 10000.0; l *= 10.0 ) {
	double x = toImageCoordinate( l * factor );
	painter.drawLine( QLineF( x, vOffset+3, x, vOffset+10 ) );
	QString tickText = toString( l * factor );
	if( tickText.size() == 1 ) {
	    painter.drawText(
		x - fontMetrics().width( tickText, 1 )/2,
		vOffset + 8 + fontMetrics().height(),
		tickText );
	}
	else {
	    painter.drawText(
		x - fontMetrics().width( tickText, 2 ),
		vOffset + 8 + fontMetrics().height(),
		tickText );
	}
    }

    /*
     *  Set the focus distance.
     */
    const QString legend = focusText + " distance";

    pen.setColor( Qt::black );
    painter.setPen( pen );
    painter.drawLine( QLineF( focus, vOffset, focus, vOffset-77.0 ) );

    /*
     *  Draw arrows.
     */
    double arrowSize = 8;
    const double M_PI_3 = M_PI/3.0;
    if( (focus + fontMetrics().width( legend ) + 20) < windowWidth ) {
	painter.drawText(
	    focus - fontMetrics().width( focusString ) - 2,
	    vOffset - 68,
	    focusString );
	painter.drawText(
	    focus + 20,
	    vOffset - 68,
	    legend );
	QPointF srcPoint( focus + 1, vOffset - 72  );
	QPointF dstPoint( focus + 18, vOffset - 72 );
	QLineF line( srcPoint, dstPoint );
	painter.drawLine( line ); 
	QPointF srcArrowP1 = srcPoint + QPointF(sin(M_PI_3) * arrowSize,
						cos(M_PI_3) * arrowSize);
	QPointF srcArrowP2 = srcPoint + QPointF(sin(M_PI - M_PI_3) * arrowSize,
						cos(M_PI - M_PI_3) * arrowSize);
	painter.setBrush( Qt::black );
	painter.drawPolygon(
	    QPolygonF() << line.p1() << srcArrowP1 << srcArrowP2 );
    }
    else {
	painter.drawText(
	    focus + 4,
	    vOffset - 68,
	    focusString );
	painter.drawText(
	    focus - fontMetrics().width( legend ) - 20,
	    vOffset - 68,
	    legend );
	QPointF srcPoint( focus - 18, vOffset - 72  );
	QPointF dstPoint( focus -  1, vOffset - 72 );
	QLineF line( srcPoint, dstPoint );
	painter.drawLine( line ); 
	QPointF dstArrowP1 = dstPoint + QPointF(sin(-M_PI_3) * arrowSize,
						cos(-M_PI_3) * arrowSize);
	QPointF dstArrowP2 = dstPoint + QPointF(sin(-M_PI + M_PI_3) * arrowSize,
						cos(-M_PI + M_PI_3) * arrowSize);
	painter.setBrush( Qt::black );
	painter.drawPolygon(
	    QPolygonF() << line.p2() << dstArrowP1 << dstArrowP2 );
    }

    /*
     *  Set the depth of field:
     *      2.5 m |<----->| 12.0m
     *         Depth of field
     */
    const QString dof = tr("Depth of field");
    const int top = vOffset + 2*fontMetrics().height();
    painter.drawLine( QLineF( near, top+10, near, top ) );
    painter.drawLine( QLineF( far, top+10, far, top ) );
    painter.drawText( near - fontMetrics().width( nearString ) - 2,
	top+10, nearString );
    painter.drawText( far + 4,
	top+10, farString );
    painter.drawText( near + (far - near)/2 - fontMetrics().width( dof )/2,
	top+10 + fontMetrics().height(), dof );
    arrowSize = (far - near)/2 - 1;
    if( arrowSize > 8 ) arrowSize = 8;
    QPointF srcPoint( near+1, top+5  );
    QPointF dstPoint( far-1, top+5 );
    QLineF line( srcPoint, dstPoint );
    painter.drawLine( line ); 
    QPointF srcArrowP1 = srcPoint + QPointF(sin(M_PI_3) * arrowSize,
					    cos(M_PI_3) * arrowSize);
    QPointF srcArrowP2 = srcPoint + QPointF(sin(M_PI - M_PI_3) * arrowSize,
					    cos(M_PI - M_PI_3) * arrowSize);
    QPointF dstArrowP1 = dstPoint + QPointF(sin(-M_PI_3) * arrowSize,
					    cos(-M_PI_3) * arrowSize);
    QPointF dstArrowP2 = dstPoint + QPointF(sin(-M_PI + M_PI_3) * arrowSize,
					    cos(-M_PI + M_PI_3) * arrowSize);
    painter.setBrush( Qt::black );
    painter.drawPolygon(
	QPolygonF() << line.p1() << srcArrowP1 << srcArrowP2 );
    painter.drawPolygon(
	QPolygonF() << line.p2() << dstArrowP1 << dstArrowP2 );

}