void
CLTypeEntryItem::MakeDragRegion(
	const STableCell&	inCell,
	RgnHandle			outGlobalDragRgn,
	Rect&				outGlobalItemBounds)
{

	// Validate pointers.
	
	ValidateThis_();
	ValidateObject_(mOutlineTable);

	// Make sure this cell is visible.

	Rect ignore;
	if (!mOutlineTable->GetLocalCellRect(inCell, ignore))
		return;

	// Find out what we're supposed to draw.

	SOutlineDrawContents drawInfo;
	GetDrawContents(inCell, drawInfo);

	// Create a bounds rect that starts at the upper left corner
	// of the icon and has the width & height of the placed item.
	
	if (drawInfo.outHasIcon && (drawInfo.outIconSuite != nil) && !::EmptyRect(&drawInfo.prIconFrame))
		outGlobalItemBounds = drawInfo.prIconFrame;
	else
		outGlobalItemBounds = drawInfo.prTextFrame;

	SDimension32 dragSize;
	mTypeEntry->GetDragSize(dragSize);
	
	outGlobalItemBounds.bottom = outGlobalItemBounds.top + dragSize.height;
	outGlobalItemBounds.right = outGlobalItemBounds.left + dragSize.width;

	// Convert to global coordinates.

	mOutlineTable->LocalToPortPoint(topLeft(outGlobalItemBounds));
	mOutlineTable->LocalToPortPoint(botRight(outGlobalItemBounds));
	mOutlineTable->PortToGlobalPoint(topLeft(outGlobalItemBounds));
	mOutlineTable->PortToGlobalPoint(botRight(outGlobalItemBounds));

	// Item bounds have been created. Now create drag region that
	// is the same size.

	RgnHandle tempRgn = ::NewRgn();
#if PP_Target_Carbon
	ThrowIfNil_(tempRgn);
#else
	ValidateHandle_((Handle) tempRgn);
#endif
	::RectRgn(tempRgn, &outGlobalItemBounds);
	::UnionRgn(outGlobalDragRgn, tempRgn, outGlobalDragRgn);
	::DisposeRgn(tempRgn);
	
}
Beispiel #2
0
void LToG (Rect *r) 
{
	Point	p1, p2;

	p1 = topLeft (*r);
	p2 = botRight (*r);
	LocalToGlobal (&p1);
	LocalToGlobal (&p2);
	Pt2Rect (p1, p2, r);
}
Beispiel #3
0
// --------------------------------------------------------------------------------------
void DisplayHelpBalloons(WindowRef prefsWindow)
{
	GrafPtr savedPort;
	Point mouseLocation;
	Rect hotRects[3];
	short hotRectID;
	static int previousHotRectID = kNotInHotRect;
	
	GetPort(&savedPort);
	SetPortWindowPort(prefsWindow);
	
	GetMouse(&mouseLocation);
	
	GetWindowProperty(prefsWindow, kAppSignature, kHotRectsTag, 3 * sizeof(Rect), NULL, 
						hotRects);
	
	for (hotRectID = kInList; hotRectID < kNotInHotRect; hotRectID++)
	{
		if (PtInRect(mouseLocation, &hotRects[hotRectID]))
		{
			if (hotRectID != previousHotRectID)
			{
				HMMessageRecord helpMessage;
				Point tips[3];
				
				helpMessage.hmmHelpType = khmmStringRes;
				helpMessage.u.hmmStringRes.hmmResID = rHelpStrings;
				helpMessage.u.hmmStringRes.hmmIndex = hotRectID + 1;
				
				GetWindowProperty(prefsWindow, kAppSignature, kBalloonTipsTag, 
									3 * sizeof(Point), NULL, tips);
				LocalToGlobal(&tips[hotRectID]);
				
				LocalToGlobal(&topLeft(hotRects[hotRectID]));
				LocalToGlobal(&botRight(hotRects[hotRectID]));
				
				HMShowBalloon(&helpMessage, tips[hotRectID], &hotRects[hotRectID], NULL, 
								kBalloonWDEFID, kTopLeftTipPointsLeftVariant, 
								kHMRegularWindow);
			}
				
			break;
		}
	}
	
	previousHotRectID = hotRectID;
	SetPort(savedPort);
}
Beispiel #4
0
void ofApp::setupScene(int width, int height)
{
    /* setup camera */
    double aspectRatio = static_cast<double>(width) / height;
    ofVec3f topLeft (-CAMERA_SIZE * aspectRatio,  CAMERA_SIZE, 0.0);
    ofVec3f botLeft (-CAMERA_SIZE * aspectRatio, -CAMERA_SIZE, 0.0);
    ofVec3f botRight( CAMERA_SIZE * aspectRatio, -CAMERA_SIZE, 0.0);
    cam = OffAxisCamera(topLeft, botLeft, botRight);
    cam.setPosition(ofVec3f(0.0, 0.0, 50.0f));

    /* calculate grid box dimension */
    ofVec3f camWidthVec = botRight - botLeft;
    double camWidth = camWidthVec.length();
    gridBox = GridBox(ofVec3f(-CAMERA_SIZE * aspectRatio, -CAMERA_SIZE, 0.0f),
            camWidth, camWidth / aspectRatio, 8.0f);
}
////////////////////////////////////////////////////////////
// Helper Function for Cascade Classifier	
//  Note: Cascade classifier is not currently used 
//  by this application. We left the functions associated
//  with this method for future reference. 
////////////////////////////////////////////////////////////
void detectAndDisplay(Mat image, string panel_cascade_name)
{
	CascadeClassifier panel_cascade;
	if (!panel_cascade.load(panel_cascade_name)){ printf("--(!)Error loading\n"); return; };

	std::vector<Rect> detectedPanels;
	Mat frame_gray;

	cvtColor(image, frame_gray, CV_BGR2GRAY);
	equalizeHist(frame_gray, frame_gray);

	//-- Detect faces
	panel_cascade.detectMultiScale(frame_gray, detectedPanels, 1.1, 20, 0 | CV_HAAR_SCALE_IMAGE, Size(200, 200));

	for (size_t i = 0; i < detectedPanels.size(); i++)
	{
		Point topLeft(detectedPanels[i].x, detectedPanels[i].y);
		Point botRight(detectedPanels[i].x + detectedPanels[i].width, detectedPanels[i].y + detectedPanels[i].height);
		rectangle(image, topLeft, botRight, Scalar(0, 0, 255), 4);
}
	//-- Show what you got
	imshow("Classifier Result", image);
}
Beispiel #6
0
Boolean
VEBackdrop::CalcLocalFrameForRootObject(
    Rect&	outFrameRect)
{

    // Validate pointers.

    ValidateThis_();

    // First make sure there is a root object.

    if (mRootObject != nil) {

        // There is, make sure it has a drawing agent.

        ValidateObject_(mRootObject.GetObject());
        VEDrawingAgent* rootAgent = mRootObject->FindDrawingAgent();
        if (rootAgent != nil) {

            // There is an agent, see if it can give us a frame.

            ValidateObject_(rootAgent);
            if (rootAgent->CalcPortFrameRect(outFrameRect)) {

                PortToLocalPoint(topLeft(outFrameRect));
                PortToLocalPoint(botRight(outFrameRect));
                return true;

            }
        }
    }

    // Nope. Root object isn't visible.

    return false;

}
/*
//-------------------------------------------------------------------------
//
// DoMouseDown
//
//-------------------------------------------------------------------------
PRBool nsMacMessagePump::DoMouseDown(EventRecord &anEvent)
{
  WindowPtr     whichWindow;
  WindowPartCode        partCode;
  PRBool  handled = PR_FALSE;
  
  partCode = ::FindWindow(anEvent.where, &whichWindow);
  
  switch (partCode)
  {
      case inNoWindow:
        break;

      case inCollapseBox:   // we never seem to get this.
      case inSysWindow:
        if ( gRollupListener && gRollupWidget )
          gRollupListener->Rollup();
        break;

      case inMenuBar:
      {
        // If a xul popup is displayed, roll it up and don't allow the click
        // through to the menu code. This is how MacOS context menus work, so
        // I think this is a valid solution.
        if ( gRollupListener && gRollupWidget )
        {
          gRollupListener->Rollup();
        }
        else
        {
          ::MenuSelect(anEvent.where);
          handled = PR_TRUE;
        }
        
        break;
      }

      case inContent:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        if ( IsWindowHilited(whichWindow) || (gRollupListener && gRollupWidget) )
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        else {
          nsCOMPtr<nsIWidget> topWidget;
          nsToolkit::GetTopWidget ( whichWindow, getter_AddRefs(topWidget) );
          nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
          if ( macWindow ) {
            // a click occurred in a background window. Use WaitMouseMove() to determine if
            // it was a click or a drag. If it was a drag, send a drag gesture to the
            // background window. We don't need to rely on the ESM to track the gesture,
            // the OS has just told us.  If it was a click, bring it to the front like normal.
            Boolean initiateDragFromBGWindow = ::WaitMouseMoved(anEvent.where);
            if ( initiateDragFromBGWindow ) {
              nsCOMPtr<nsIEventSink> sink ( do_QueryInterface(topWidget) );
              if ( sink ) {
                // dispach a mousedown, an update event to paint any changes,
                // then the drag gesture event
                PRBool handled = PR_FALSE;
                sink->DispatchEvent ( &anEvent, &handled );
                
                EventRecord updateEvent = anEvent;
                updateEvent.what = updateEvt;
                updateEvent.message = NS_REINTERPRET_CAST(UInt32, whichWindow);
                sink->DispatchEvent ( &updateEvent, &handled );
                
                sink->DragEvent ( NS_DRAGDROP_GESTURE, anEvent.where.h, anEvent.where.v, 0L, &handled );                
              }
            }
            else {
              PRBool enabled;
              if (NS_SUCCEEDED(topWidget->IsEnabled(&enabled)) && !enabled)
                ::SysBeep(1);
              else
                macWindow->ComeToFront();
            }
            handled = PR_TRUE;
          }
        }
        break;
      }

      case inDrag:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);

        Point   oldTopLeft = {0, 0};
        ::LocalToGlobal(&oldTopLeft);
        
        // roll up popups BEFORE we start the drag
        if ( gRollupListener && gRollupWidget )
          gRollupListener->Rollup();

        Rect screenRect;
        ::GetRegionBounds(::GetGrayRgn(), &screenRect);
        ::DragWindow(whichWindow, anEvent.where, &screenRect);

        Point   newTopLeft = {0, 0};
        ::LocalToGlobal(&newTopLeft);

        // only activate if the command key is not down
        if (!(anEvent.modifiers & cmdKey))
        {
          nsCOMPtr<nsIWidget> topWidget;
          nsToolkit::GetTopWidget(whichWindow, getter_AddRefs(topWidget));
          
          nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
          if ( macWindow )
            macWindow->ComeToFront();
        }
        
        // Dispatch the event because some windows may want to know that they have been moved.
        anEvent.where.h += newTopLeft.h - oldTopLeft.h;
        anEvent.where.v += newTopLeft.v - oldTopLeft.v;
        
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        break;
      }

      case inGrow:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);

        Rect sizeLimit;
        sizeLimit.top = kMinWindowHeight;
        sizeLimit.left = kMinWindowWidth;
        sizeLimit.bottom = 0x7FFF;
        sizeLimit.right = 0x7FFF;

        Rect newSize;
        ::ResizeWindow(whichWindow, anEvent.where, &sizeLimit, &newSize);

        Point newPt = botRight(newSize);
        ::LocalToGlobal(&newPt);
        newPt.h -= 8, newPt.v -= 8;
        anEvent.where = newPt;  // important!
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);

        break;
      }

      case inGoAway:
      {
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        if (::TrackGoAway(whichWindow, anEvent.where)) {
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        }
        break;
      }

      case inZoomIn:
      case inZoomOut:
        if (::TrackBox(whichWindow, anEvent.where, partCode))
        {
          if (partCode == inZoomOut)
          {
            nsCOMPtr<nsIWidget> topWidget;
            nsToolkit::GetTopWidget ( whichWindow, getter_AddRefs(topWidget) );
            nsCOMPtr<nsPIWidgetMac> macWindow ( do_QueryInterface(topWidget) );
            if ( macWindow )
              macWindow->CalculateAndSetZoomedSize();
          }
          // !!!  Do not call ZoomWindow before calling DispatchOSEventToRaptor
          //    otherwise nsMacEventHandler::HandleMouseDownEvent won't get
          //    the right partcode for the click location
          
          handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        }
        break;

      case inToolbarButton:           // Mac OS X only
        nsGraphicsUtils::SafeSetPortWindowPort(whichWindow);
        handled = DispatchOSEventToRaptor(anEvent, whichWindow);
        break;

  }

  return handled;
}
bool CFXTransExplodingCubes::LoadData(CResourceList* pResourceList)
{
	// Create RTT Texture

	CVarInt::CValueInt valueInt;

	EvaluateVar("RenderTex Width",  0.0f, &valueInt);
	if(valueInt.GetValue() < 1) valueInt.SetValue(1);
	int nWidthPwr = MYROUND(log10f(valueInt.GetValue()) / log10f(2));

	EvaluateVar("RenderTex Height", 0.0f, &valueInt);
	if(valueInt.GetValue() < 1) valueInt.SetValue(1);
	int nHeightPwr = MYROUND(log10f(valueInt.GetValue()) / log10f(2));

	int nWidth  = pow(2, nWidthPwr);
	int nHeight = pow(2, nHeightPwr);

	UtilGL::Texturing::STexLoadOptions texOptions;
	texOptions.SetDefaults();
	texOptions.eFilter = UtilGL::Texturing::FILTER_LINEAR;

	m_textureRTT.LoadFlat(nWidth, nHeight, CVector4(0.0f, 0.0f, 0.0f, 1.0f), false, false, &texOptions);

	// Create cubes

	CVarInt::CValueInt     valueXCubes;
	CVarInt::CValueInt     valueYCubes;
	CVarInt::CValueInt     valueSeed;
	CVarFloat::CValueFloat valueAngleMultiple;
	CVarFloat::CValueFloat valueDepth;
	CVarFloat::CValueFloat valueAngleStep;

	CVarFloat::CValueFloat valueAccelX;
	CVarFloat::CValueFloat valueAccelY;
	CVarFloat::CValueFloat valueAccelZ;
	CVarFloat::CValueFloat valueSpeedX;
	CVarFloat::CValueFloat valueSpeedY;
	CVarFloat::CValueFloat valueSpeedZ;
	CVarFloat::CValueFloat valueAssimetry;
	CVarFloat::CValueFloat valueMaxRotation;
	CVarFloat::CValueFloat valueVariation;

	EvaluateVar("X Cubes",        0.0f, &valueXCubes);
	EvaluateVar("Y Cubes",        0.0f, &valueYCubes);
	EvaluateVar("Seed",		      0.0f, &valueSeed);
	EvaluateVar("Z Depth",        0.0f, &valueDepth);
	EvaluateVar("Angle Step",     0.0f, &valueAngleStep);
	EvaluateVar("Accel X",        0.0f, &valueAccelX);
	EvaluateVar("Accel Y",        0.0f, &valueAccelY);
	EvaluateVar("Accel Z",        0.0f, &valueAccelZ);
	EvaluateVar("Start Speed X",  0.0f, &valueSpeedX);
	EvaluateVar("Start Speed Y",  0.0f, &valueSpeedY);
	EvaluateVar("Start Speed Z",  0.0f, &valueSpeedZ);
	EvaluateVar("Assimetry",      0.0f, &valueAssimetry);
	EvaluateVar("Max Rotation",   0.0f, &valueMaxRotation);
	EvaluateVar("Variation",      0.0f, &valueVariation);

	CVector3 v3Accel(valueAccelX.GetValue(), valueAccelY.GetValue(), valueAccelZ.GetValue());
	CVector3 v3Speed(valueSpeedX.GetValue(), valueSpeedY.GetValue(), valueSpeedZ.GetValue());

	int xRes = valueXCubes.GetValue() > 1 ? valueXCubes.GetValue() : 1;
	int yRes = valueYCubes.GetValue() > 1 ? valueYCubes.GetValue() : 1;

	float fSizeX = 1.0f / xRes;
	float fSizeY = 1.0f / yRes;

	srand(valueSeed.GetValue());

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0f, 1.33f, 1.0f, 100.0f);

	UtilGL::Transforming::ClearMatrix(UtilGL::Transforming::MATRIX_WORLD);
	UtilGL::Transforming::ClearMatrix(UtilGL::Transforming::MATRIX_VIEW);

	for(int y = 0; y < yRes; y++)
	{
		for(int x = 0; x < xRes; x++)
		{
			SCube cube;

			cube.fU  = x * fSizeX;
			cube.fV  = 1.0f - (y * fSizeY);
			cube.fU2 = x * fSizeX + fSizeX;
			cube.fV2 = 1.0f - (y * fSizeY + fSizeY);

			CVector3 upLeft  (x * fSizeX,          y * fSizeY,          0.5f);
			CVector3 botRight(x * fSizeX + fSizeX, y * fSizeY + fSizeY, 0.5f);

			UtilGL::Transforming::NormViewportToLocal(&upLeft);
			UtilGL::Transforming::NormViewportToLocal(&botRight);

			float fHalfX = (botRight.X() - upLeft.X()) * 0.5f;
			float fHalfY = (botRight.Y() - upLeft.Y()) * 0.5f;
			float fHalfZ = valueDepth.GetValue() * 0.5f;

			cube.v1.Set(-fHalfX, -fHalfY, +fHalfZ);
			cube.v2.Set(-fHalfX, +fHalfY, +fHalfZ);
			cube.v3.Set(+fHalfX, +fHalfY, +fHalfZ);
			cube.v4.Set(+fHalfX, -fHalfY, +fHalfZ);
			cube.v5.Set(-fHalfX, -fHalfY, -fHalfZ);
			cube.v6.Set(-fHalfX, +fHalfY, -fHalfZ);
			cube.v7.Set(+fHalfX, +fHalfY, -fHalfZ);
			cube.v8.Set(+fHalfX, -fHalfY, -fHalfZ);

			cube.v3Center.Set(	(x * fSizeX) + (fSizeX * 0.5f),
								(y * fSizeY) + (fSizeY * 0.5f),
								0.5f);

			cube.v3Accel    = v3Accel * ComputeRandWithVariation(1.0f, valueVariation.GetValue()) * ((botRight.Y() - upLeft.Y()) * xRes);
			cube.v3Speed    = v3Speed * ComputeRandWithVariation(1.0f, valueVariation.GetValue()) * ((botRight.Y() - upLeft.Y()) * xRes);

			cube.fStartTime = (MYFABSF(x - (xRes / 2.0f)) / (float)(xRes / 2.0f)) * valueAssimetry.GetValue();
			cube.fRotation  = ComputeRand(0.0f, valueMaxRotation.GetValue());

			UtilGL::Transforming::NormViewportToLocal(&cube.v3Center);

			cube.fTStart = 0.0f;
			cube.fTEnd   = 1.0f;

			m_vecCubes.push_back(cube);
		}
	}

	return true;
}
void
sstSequence::ClampBeats()
{
	float margin = 100.f;

	vsScreen *screen = vsSystem::GetScreen();

	float fov = screen->GetScene(0)->GetFOV();
	float screenHeight = fov;
	float screenWidth = screenHeight * screen->GetAspectRatio();

	float topEdge = (screenHeight * -.5f) + 100.0f + margin;
	float botEdge = 0.f;	// never go below the halfway point, because that's just not nice.  :)
	float leftEdge = (screenWidth * -0.5f) + margin;
	float rightEdge = (screenWidth * 0.5f) - margin;
//	bool clampedSuccessfully = false;

	// if we're supposed to be on the right, clamp us onto the right side.

	if ( m_onRight )
		leftEdge = 0.f;
	else
		rightEdge = 0.f;

	vsVector2D worldBeatPos[MAX_BEATS];
	vsVector2D topLeft(10000.0f,10000.0f);		// arbitrary large values
	vsVector2D botRight(-1000.0f,-10000.0f);	// arbitrary small values

	for ( int i = 0; i < m_beatCount; i++ )
	{
		vsTransform2D t = GetTransformAtTime( m_segment[i].m_time );
		worldBeatPos[i] = t.ApplyTo( m_segment[i].m_position );

		if ( worldBeatPos[i].x < topLeft.x )
			topLeft.x = worldBeatPos[i].x;
		if ( worldBeatPos[i].x > botRight.x )
			botRight.x = worldBeatPos[i].x;
		if ( worldBeatPos[i].y < topLeft.y )
			topLeft.y = worldBeatPos[i].y;
		if ( worldBeatPos[i].y > botRight.y )
			botRight.y = worldBeatPos[i].y;
	}

	float width = botRight.x - topLeft.x;
	float height = botRight.y - topLeft.y;

	float usableScreenWidth = rightEdge - leftEdge;
	float usableScreenHeight = botEdge - topEdge;

	if ( width > usableScreenWidth || height > usableScreenHeight )
	{
		// we're never going to make this fit;  make our translation smaller!
		//printf("Too big!  Try again!\n");
		return DoneAddingBeats();
	}

//	float widthRange = usableScreenWidth - width;
//	float heightRange = usableScreenHeight - height;

	vsVector2D minAdjustment = vsVector2D::Zero;
	vsVector2D maxAdjustment = vsVector2D::Zero;
	if ( topLeft.x < leftEdge )
	{
		minAdjustment.x = leftEdge - topLeft.x;
		maxAdjustment.x = rightEdge - botRight.x;
	}
	else if ( botRight.x > rightEdge )
	{
		minAdjustment.x = rightEdge - botRight.x;
		maxAdjustment.x = leftEdge - topLeft.x;
	}

	if ( topLeft.y < topEdge )
	{
		minAdjustment.y = topEdge - topLeft.y;
		maxAdjustment.y = botEdge - botRight.y;
	}
	else if ( botRight.y > botEdge )
	{
		minAdjustment.y = botEdge - botRight.y;
		maxAdjustment.y = topEdge - topLeft.y;
	}

	vsVector2D adjustment( vsRandom::GetFloat(minAdjustment.x, maxAdjustment.x),
						  vsRandom::GetFloat(minAdjustment.y, maxAdjustment.y) );

	m_transformA.SetTranslation( m_transformA.GetTranslation() + adjustment );
	m_transformB.SetTranslation( m_transformB.GetTranslation() + adjustment );
}
Beispiel #11
0
void gridToPolygon(phys::Collision* c, phys::RigidBody *a, phys::RigidBody *b)
{
    c->addManifold();
    c->getLastManifold()->contactCount = 0;

    GridShape* grid = reinterpret_cast<GridShape*>(a->getShape());
    phys::PolygonShape* poly = reinterpret_cast<phys::PolygonShape*>(b->getShape());

    sf::Vector2f topLeft(FLT_MAX, FLT_MAX);
    sf::Vector2f botRight(-FLT_MAX, -FLT_MAX);

    for (unsigned int i = 0; i < poly->getVertices().size(); i++)
    {
        // Retrieve a face normal from A
        sf::Vector2f n = poly->getNormals()[i];
        sf::Vector2f nw = poly->getU() * n;

        // Transform face normal into B's model space
        phys::Mat2 buT = grid->getU().transpose( );
        n = buT * nw;

        // Retrieve vertex on face from A, transform into
        // B's model space
        sf::Vector2f v = poly->getVertices()[i];
        v = (poly->getU() * v) + b->getPosition();
        v -= a->getPosition();
        v = buT * v;

        poly->transformedVertices[i] = v;
        poly->transformedNormals[i] = n;

        if (v.x < topLeft.x)
            topLeft.x = v.x;
        if (v.y < topLeft.y)
            topLeft.y = v.y;
        if (v.x > botRight.x)
            botRight.x = v.x;
        if (v.y > botRight.y)
            botRight.y = v.y;
    }

    int left = floor(topLeft.x/(PTU/TILE_SIZE))-1;
    int top = floor(topLeft.y/(PTU/TILE_SIZE))-1;
    int right = ceil(botRight.x/(PTU/TILE_SIZE))+1;
    int bot = ceil(botRight.y/(PTU/TILE_SIZE))+1;

    if (!grid->getGrid()->mWrapX)
    {
        left = std::max(left, 0);
        right = std::min(right, grid->getGrid()->mSizeX-1);
    }
	top = std::max(top, 0);
    bot = std::min(bot, grid->getGrid()->mSizeY-1);

    // Tile size
    float tileSize = PTU/TILE_SIZE;

    // Find the tile with the least overlap in the collision
    sf::Vector2f tileVerts[4];
    int tileVertCount;
    float tilePenetration = 0.f;
    float polyPenetration = 0.f;
    int tileFace;
    int polyFace;

    sf::Vector2f tileNormals[4];

    sf::Vector2f usedNormals[20];
    int usedNormalCount = 0;

    for (int y = top; y <= bot; y++)
    {
        for (int _x = left; _x <= right; _x++)
        {
            int x = _x;
            if (grid->getGrid()->mWrapX)
                x = grid->getGrid()->wrapX(x);

            if (!grid->getGrid()->mTiles[y][x].isSolid())
                continue;

            int left = x-1;
            int right = x+1;
            int up = y-1;
            int down = y+1;

            if (grid->getGrid()->mWrapX)
            {
                left = grid->getGrid()->wrapX(left);
                right = grid->getGrid()->wrapX(right);
            }

            bool leftT = false;
            bool rightT = false;
            bool upT = false;
            bool downT = false;

            if (left >= 0 && grid->getGrid()->mTiles[y][left].isSolid())
                leftT = true;
            if (right < grid->getGrid()->mSizeX && grid->getGrid()->mTiles[y][right].isSolid())
                rightT = true;
            if (up >= 0 && grid->getGrid()->mTiles[up][x].isSolid())
                upT = true;
            if (down < grid->getGrid()->mSizeY && grid->getGrid()->mTiles[down][x].isSolid())
                downT = true;

            sf::Vector2f start(_x*tileSize, y*tileSize);

            if (!leftT && !rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start + sf::Vector2f(tileSize/2, 0);
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = normalize(sf::Vector2f(-0.5, -1.f));
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = normalize(sf::Vector2f(0.5, -1.f));
            }
            else if (!leftT && rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start + sf::Vector2f(tileSize, 0);
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = normalize(sf::Vector2f(-1.f, -1.f));
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = sf::Vector2f(1.f, 0.f);
            }
            else if (leftT && !rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start;
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = sf::Vector2f(-1.f, 0.f);
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = normalize(sf::Vector2f(1.f, -1.f));
            }
            else
            {
                tileVertCount = 4;
                tileVerts[0] = start;
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);
                tileVerts[3] = start + sf::Vector2f(tileSize, 0);

                tileNormals[0] = sf::Vector2f(-1, 0);
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = sf::Vector2f(1, 0);
                tileNormals[3] = sf::Vector2f(0, -1);
            }


            // Check for a separating axis with A's face planes
            int faceA;
            float penetrationA = findAxisLeastPenetration(&faceA, poly->transformedVertices.data(),
                                                          poly->transformedNormals.data(), poly->transformedVertices.size(), tileVerts, tileVertCount);
            if(penetrationA >= 0.0f || phys::equal(penetrationA, 0.f))
                continue;

            // Check for a separating axis with B's face planes
            int faceB;
            float penetrationB = findAxisLeastPenetration(&faceB, tileVerts, tileNormals, tileVertCount,
                                                          poly->transformedVertices.data(), poly->transformedVertices.size());
            if(penetrationB >= 0.0f || phys::equal(penetrationB, 0.f))
                continue;

            tilePenetration = penetrationB;
            polyPenetration = penetrationA;
            tileFace = faceB;
            polyFace = faceA;

            sf::Uint32 referenceIndex;
            bool flip; // Always point from a to b

            phys::RigidBody* ref;
            sf::Vector2f* refVerts;
            sf::Vector2f* refNormals;
            int refCount;
            phys::RigidBody* inc;
            sf::Vector2f* incVerts;
            sf::Vector2f* incNormals;
            int incCount;

            // Determine which shape contains reference face
            if(phys::biasGreaterThan( tilePenetration, polyPenetration ))
            {
                ref = a;
                refVerts = tileVerts;
                refNormals = tileNormals;
                refCount = tileVertCount;

                inc = b;
                incVerts = poly->transformedVertices.data();
                incNormals = poly->transformedNormals.data();
                incCount = poly->transformedVertices.size();

                referenceIndex = tileFace;
                flip = false;
            }
            else
            {
                ref = b;
                refVerts = poly->transformedVertices.data();
                refNormals = poly->transformedNormals.data();
                refCount = poly->transformedVertices.size();

                inc = a;
                incVerts = tileVerts;
                incNormals = tileNormals;
                incCount = tileVertCount;

                referenceIndex = polyFace;
                flip = true;
            }

            bool used = false;
            for (int i = 0; i < usedNormalCount; i++)
            {
                if (refNormals[referenceIndex] == usedNormals[i])
                {
                    used = true;
                    break;
                }
            }

            if (used)
                continue;

            usedNormals[usedNormalCount] = refNormals[referenceIndex];
            usedNormalCount++;

            // World space incident face
            sf::Vector2f incidentFace[2];
            findIncidentFace(incidentFace, refVerts, refNormals, refCount, incVerts, incNormals, incCount, referenceIndex);

            //        y
            //        ^  ->n       ^
            //      +---c ------posPlane--
            //  x < | i |\
            //      +---+ c-----negPlane--
            //             \       v
            //              r
            //
            //  r : reference face
            //  i : incident poly
            //  c : clipped point
            //  n : incident normal

            // Setup reference face vertices
            sf::Vector2f v1 = refVerts[referenceIndex];
            referenceIndex = referenceIndex + 1 == refCount ? 0 : referenceIndex + 1;
            sf::Vector2f v2 = refVerts[referenceIndex];

            // Calculate reference face side normal in world space
            sf::Vector2f sidePlaneNormal = (v2 - v1);
            sidePlaneNormal = phys::normalize(sidePlaneNormal);

            // Orthogonalize
            sf::Vector2f refFaceNormal( sidePlaneNormal.y, -sidePlaneNormal.x );

            // ax + by = c
            // c is distance from origin
            float refC = phys::dot( refFaceNormal, v1 );
            float negSide = -phys::dot( sidePlaneNormal, v1 );
            float posSide =  phys::dot( sidePlaneNormal, v2 );

            // Clip incident face to reference face side planes
            if(clip( -sidePlaneNormal, negSide, incidentFace ) < 2)
                return; // Due to floating point error, possible to not have required points

            if(clip(  sidePlaneNormal, posSide, incidentFace ) < 2)
                return; // Due to floating point error, possible to not have required points

            // Flip
            c->getLastManifold()->normal = flip ? -refFaceNormal : refFaceNormal;

            // Keep points behind reference face
            sf::Uint32 cp = 0; // clipped points behind reference face
            float separation = phys::dot( refFaceNormal, incidentFace[0] ) - refC;
            if(separation <= 0.0f)
            {
                c->getLastManifold()->contacts[cp] = incidentFace[0];
                c->getLastManifold()->penetration = -separation;
                ++cp;
            }
            else
                c->getLastManifold()->penetration = 0;

            separation = phys::dot( refFaceNormal, incidentFace[1] ) - refC;
            if(separation <= 0.0f)
            {
                c->getLastManifold()->contacts[cp] = incidentFace[1];

                c->getLastManifold()->penetration += -separation;
                ++cp;

                // Average penetration
                c->getLastManifold()->penetration /= (float)cp;
            }

            c->getLastManifold()->contactCount = cp;

            c->addManifold();
            c->getLastManifold()->contactCount = 0;
        }
    }
}
Beispiel #12
0
void circleToGrid(phys::Collision* c, phys::RigidBody *a, phys::RigidBody *b)
{
    GridShape* grid = reinterpret_cast<GridShape*>(b->getShape());
    phys::CircleShape* circle = reinterpret_cast<phys::CircleShape*>(a->getShape());

    // Transform circle center to Polygon model space
    sf::Vector2f center = a->getPosition();
    center = grid->getU().transpose() * (center - b->getPosition());

    sf::Vector2f topLeft(center.x-circle->getRadius(), center.y-circle->getRadius());
    sf::Vector2f botRight(center.x+circle->getRadius(), center.y+circle->getRadius());

    int left = floor(topLeft.x/(PTU/TILE_SIZE))-1;
    int top = floor(topLeft.y/(PTU/TILE_SIZE))-1;
    int right = ceil(botRight.x/(PTU/TILE_SIZE))+1;
    int bot = ceil(botRight.y/(PTU/TILE_SIZE))+1;

    if (!grid->getGrid()->getWrapX())
    {
        left = std::max(left, 0);
        right = std::min(right, grid->getGrid()->getSizeX()-1);
    }
	top = std::max(top, 0);
    bot = std::min(bot, grid->getGrid()->getSizeY()-1);

    // Tile size
    float tileSize = PTU/TILE_SIZE;

    // Find the tile with the least overlap in the collision
    sf::Vector2f tileVerts[4];
    int tileVertCount;
    sf::Vector2f tileNormals[4];

    sf::Vector2f usedNormals[20];
    int usedNormalCount = 0;

    for (int y = top; y <= bot; y++)
    {
        for (int _x = left; _x <= right; _x++)
        {
            c->addManifold();
            c->getLastManifold()->contactCount = 0;

            int x = _x;
            if (grid->getGrid()->getWrapX())
                x = grid->getGrid()->wrapX(x);

            if (!grid->getGrid()->mTiles[y][x].isSolid())
                continue;

            int left = x-1;
            int right = x+1;
            int up = y-1;
            int down = y+1;

            if (grid->getGrid()->mWrapX)
            {
                left = grid->getGrid()->wrapX(left);
                right = grid->getGrid()->wrapX(right);
            }

            bool leftT = false;
            bool rightT = false;
            bool upT = false;
            bool downT = false;

            if (left >= 0 && grid->getGrid()->mTiles[y][left].isSolid())
                leftT = true;
            if (right < grid->getGrid()->mSizeX && grid->getGrid()->mTiles[y][right].isSolid())
                rightT = true;
            if (up >= 0 && grid->getGrid()->mTiles[up][x].isSolid())
                upT = true;
            if (down < grid->getGrid()->mSizeY && grid->getGrid()->mTiles[down][x].isSolid())
                downT = true;

            sf::Vector2f start(_x*tileSize, y*tileSize);

            if (!leftT && !rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start + sf::Vector2f(tileSize/2, 0);
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = normalize(sf::Vector2f(-0.5, -1.f));
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = normalize(sf::Vector2f(0.5, -1.f));
            }
            else if (!leftT && rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start + sf::Vector2f(tileSize, 0);
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = normalize(sf::Vector2f(-1.f, -1.f));
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = sf::Vector2f(1.f, 0.f);
            }
            else if (leftT && !rightT && !upT && downT)
            {
                tileVertCount = 3;
                tileVerts[0] = start;
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);

                tileNormals[0] = sf::Vector2f(-1.f, 0.f);
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = normalize(sf::Vector2f(1.f, -1.f));
            }
            else
            {
                tileVertCount = 4;
                tileVerts[0] = start;
                tileVerts[1] = start + sf::Vector2f(0, tileSize);
                tileVerts[2] = start + sf::Vector2f(tileSize, tileSize);
                tileVerts[3] = start + sf::Vector2f(tileSize, 0);

                tileNormals[0] = sf::Vector2f(-1, 0);
                tileNormals[1] = sf::Vector2f(0, 1);
                tileNormals[2] = sf::Vector2f(1, 0);
                tileNormals[3] = sf::Vector2f(0, -1);
            }


            // Find edge with minimum penetration
            // Exact concept as using support points in Polygon vs Polygon
            float separation = -FLT_MAX;
            sf::Uint32 faceNormal = 0;
            bool done = false;
            for(sf::Uint32 i = 0; i < tileVertCount; ++i)
            {
                float s = dot( tileNormals[i], center - tileVerts[i] );

                if(s > circle->getRadius())
                {
                    done = true;
                    break;
                }

                if(s > separation)
                {
                    separation = s;
                    faceNormal = i;
                }
            }

            if (done)
                continue;

            /*bool used = false;
            for (int i = 0; i < usedNormalCount; i++)
            {
                if (tileNormals[faceNormal] == usedNormals[i])
                {
                    used = true;
                    break;
                }
            }

            if (used)
                continue;

            usedNormals[usedNormalCount] = tileNormals[faceNormal];
            usedNormalCount++;*/

            // Grab face's vertices
            sf::Vector2f v1 = tileVerts[faceNormal];
            sf::Uint32 i2 = faceNormal + 1 < tileVertCount ? faceNormal + 1 : 0;
            sf::Vector2f v2 = tileVerts[i2];

            // Check to see if center is within polygon
            if(separation < EPSILON)
            {
                c->getLastManifold()->contactCount = 1;
                c->getLastManifold()->normal = -(grid->getU() * tileNormals[faceNormal]);
                c->getLastManifold()->contacts[0] = c->getLastManifold()->normal * circle->getRadius() + b->getPosition();
                c->getLastManifold()->penetration = circle->getRadius();
                continue;
            }

            // Determine which voronoi region of the edge center of circle lies within
            float dot1 = dot( center - v1, v2 - v1 );
            float dot2 = dot( center - v2, v1 - v2 );
            c->getLastManifold()->penetration = circle->getRadius() - separation;

            // Closest to v1
            if(dot1 <= 0.0f)
            {
                if(lengthSqr( center - v1 ) > circle->getRadius() * circle->getRadius())
                    continue;

                c->getLastManifold()->contactCount = 1;
                sf::Vector2f n = v1 - center;
                n = grid->getU() * n;
                n = normalize(n);
                c->getLastManifold()->normal = n;
                v1 = grid->getU() * v1 + a->getPosition();
                c->getLastManifold()->contacts[0] = v1;
            }

            // Closest to v2
            else if(dot2 <= 0.0f)
            {
                if(lengthSqr( center - v2 ) > circle->getRadius() * circle->getRadius())
                    continue;

                c->getLastManifold()->contactCount = 1;
                sf::Vector2f n = v2 - center;
                v2 = grid->getU() * v2 + a->getPosition();
                c->getLastManifold()->contacts[0] = v2;
                n = grid->getU() * n;
                n = normalize(n);
                c->getLastManifold()->normal = n;
            }

            // Closest to face
            else
            {
                sf::Vector2f n = tileNormals[faceNormal];
                if(dot( center - v1, n ) > circle->getRadius())
                    continue;

                n = grid->getU() * n;
                c->getLastManifold()->normal = -n;
                c->getLastManifold()->contacts[0] = c->getLastManifold()->normal * circle->getRadius() + b->getPosition();
                c->getLastManifold()->contactCount = 1;
            }
        }
    }
}
Beispiel #13
0
MTV Collision::getCollision(const sf::Sprite& object1,Entity::ENTITY_SHAPE shape1,const sf::Sprite& object2,Entity::ENTITY_SHAPE shape2){
	//Use Separating Axis Theorem to determine whether two objects are overlapping
	//See documentation for full explanation of this algorithm

	//Get the oriented bounding box in world coordinates (includes rotation) of objects
	OBB obb1 = getOBB(object1);
	OBB obb2 = getOBB(object2);
	float rot = object1.getRotation();

	double overlap = LONG_MAX;
	maths::Vector2 smallest(0,0);

	std::vector<maths::Vector2> axis1;
	std::vector<maths::Vector2> axis2;

	maths::Vector2 circleCentre1;
	maths::Vector2 circleCentre2;

	sf::FloatRect gbounds1 = object1.getGlobalBounds();
	sf::FloatRect gbounds2 = object2.getGlobalBounds();
	 
	//Find all the axes to check using SAT based on shapes of objects
	//Works with squares/rectangles or circles
	//Rectangles only need 2 axes because they have 2 sets of parallel lines
	if(shape1 == Entity::SHAPE_CIRCLE && shape2 == Entity::SHAPE_CIRCLE){
		//If both shapes are circles, the only axis needed is the axis between centres of circles
		circleCentre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
		circleCentre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
		axis1.push_back(maths::Vector2(circleCentre1 - circleCentre2).normalise());

	}else if(shape1 != shape2){ //if one shape is circle and one shape is rectangle
		maths::Vector2 circleCentre;
		sf::FloatRect squareRect;
		float rotation;

		//First get the unrotated bounding box and centre of the circle of the 2 objects
		if(shape1 == Entity::SHAPE_CIRCLE){
			circleCentre = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
			circleCentre1 = circleCentre;
			squareRect = getOriginalBoundingBox(object2);
			rotation = object2.getRotation();
		}else if(shape2 == Entity::SHAPE_CIRCLE){
			circleCentre = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
			circleCentre2 = circleCentre;
			squareRect = getOriginalBoundingBox(object1);
			rotation = object1.getRotation();
		}

		maths::Vector2 squareCentre(squareRect.left + squareRect.width / 2, squareRect.top + squareRect.height / 2);
		OBB* square = (shape1 == Entity::SHAPE_SQUARE ? &obb1 : &obb2);
		maths::Vector2 relativeCircleCentre = circleCentre.rotate(-rotation, squareCentre); //get circle centre in relation to the rotated square
		bool vertice = false;
		maths::Vector2 axis;

		maths::Vector2 topLeft(squareRect.left, squareRect.top);
		maths::Vector2 topRight(squareRect.left + squareRect.width, squareRect.top);
		maths::Vector2 botLeft(squareRect.left, squareRect.top + squareRect.height);
		maths::Vector2 botRight(squareRect.left + squareRect.width, squareRect.top + squareRect.height);

		//Get the closest vertex of the rectangle to the circle centre.
		//The axis to check is the vector between these 2 points.
		if(circleCentre.x < topLeft.x){
			if(circleCentre.y < topLeft.y){
				vertice = true;
				axis = topLeft;
			}else if(circleCentre.y >  botLeft.y){
				vertice = true;
				axis = botLeft;
			}else{
				axis = maths::Vector2(topLeft - botLeft).normalise();
			}
		}else if(circleCentre.x > topRight.x){
			if(circleCentre.y < topLeft.y){
				vertice = true;
				axis = topRight;
			}else if(circleCentre.y >  botLeft.y){
				vertice = true;
				axis = botRight;
			}else{
				axis = maths::Vector2(topRight - botRight).normalise();
			}
		}else{
			if(circleCentre.y < topLeft.y){
				axis = maths::Vector2(topRight - topLeft).normalise();
			}else if(circleCentre.y >  botLeft.y){
				axis = maths::Vector2(botLeft - botRight).normalise();
			}else{
				//contains point!
			}
		}

		if(vertice){
			axis1.push_back(maths::Vector2(circleCentre - axis).normalise());
		}else{
			axis1.push_back(maths::Vector2(topRight - topLeft).normalise());
			axis1.push_back(maths::Vector2(topRight - botRight).normalise());
		}
	}else{ //If both shapes are rectangles
		//Get vectors for sides of shapes
		maths::Vector2 Xside1(obb1.bot_left - obb1.bot_right);
		maths::Vector2 Yside1(obb1.top_left - obb1.bot_left);
		maths::Vector2 Xside2(obb2.bot_left - obb2.bot_right);
		maths::Vector2 Yside2(obb2.top_left - obb2.bot_left);

		//Axes requires are perpendicular to the sides of the shape
		//Vector2.perpendicular() normalises for greater accuracy
		axis1.push_back(Xside1.perpendicular());
		axis1.push_back(Yside1.perpendicular());
		axis2.push_back(Xside2.perpendicular());
		axis2.push_back(Yside2.perpendicular());
	}

	//We have all the axes to check.
	//Now find details on collisions with projections.

	for(int i=0;i<axis1.size();i++){
		//Get projection of axis for both shapes
		maths::Vector2 axis = axis1[i];
		Projection projection1 = project(obb1, axis);
		if(shape1 == Entity::SHAPE_CIRCLE){
			float radius = gbounds1.width / 2;
			projection1 = projectCircle(circleCentre1, radius, axis);
		}
		Projection projection2 = project(obb2, axis);
		if (shape2 == Entity::SHAPE_CIRCLE){
			float radius = gbounds2.width / 2;
			projection2 = projectCircle(circleCentre2, radius, axis);
		}

		//If a projection does not overlap, we know the objects do not collide so we can exit the function.
		//Otherwise, the MTV (minimum translation vector required to make the objects not collide) is calculated.

		if(!projection1.overlap(projection2)){
			return MTV::NONE;
		}else{
			//The axis with the smallest overlap is the axis used to calculate MTV, so record it.
			double o = projection1.getOverlap(projection2);
			if(o < overlap){
				overlap = o; //set smallest overlap
				smallest = axis; //set smallest separation vector
			}
		}
	}
	
	//Repeat the same process as above with the other set of axes.
	for(int i=0;i<axis2.size();i++){
		maths::Vector2 axis = axis2[i];
		Projection projection1 = project(obb1, axis);
		if(shape1 == Entity::SHAPE_CIRCLE){
			float radius = gbounds1.width/2;
			projection1 = projectCircle(circleCentre1, radius, axis);
		}
		Projection projection2 = project(obb2,axis);
		if(shape2 == Entity::SHAPE_CIRCLE){
			float radius = gbounds2.width / 2;
			projection2 = projectCircle(circleCentre2, radius, axis);
		}

		if(!projection1.overlap(projection2)){
			return MTV::NONE;
		}else{
			double o = projection1.getOverlap(projection2);
			if(o < overlap){
				overlap = o;
				smallest = axis;
			}
		}
	}
	//Get the vector from the centre of object 2 to the centre of object 1
	maths::Vector2 centre1 = maths::Vector2(gbounds1.left + gbounds1.width / 2, gbounds1.top + gbounds1.height / 2);
	maths::Vector2 centre2 = maths::Vector2(gbounds2.left + gbounds2.width / 2, gbounds2.top + gbounds2.height / 2);
	maths::Vector2 between = centre1 - centre2;
	//If the separation vector is in the opposite direction of 'between', flip it round by negating it
	if(between.dot(smallest) < 0){
		smallest = -smallest;
	}
	MTV mtv(overlap, smallest);
	return mtv;
}