Search code examples
iosrotationspriteglkitatlas

How to use GLKit to rotate about the center of a sprite off an atlas


I have a texture that follows a user's finger in GLKit. I calculate the radian to draw the angle at using arctan between the two points.

Part of the trick here is to keep the object centered underfed the finger. So i have introduced the idea of an anchor point so that things can be drawn relative to their origin or center. My goal is to move the sprite into place and then rotate. I have the following code in my renderer.

// lets adjust for our location based on our anchor point.
GLKVector2 adjustment = GLKVector2Make(self.spriteSize.width * self.anchorPoint.x, 
                                       self.spriteSize.height * self.anchorPoint.y);

GLKVector2 adjustedPosition = GLKVector2Subtract(self.position, adjustment);
GLKMatrix4 modelMatrix = GLKMatrix4Multiply(GLKMatrix4MakeTranslation(adjustedPosition.x, adjustedPosition.y, 1.0), GLKMatrix4MakeScale(adjustedScale.x, adjustedScale.y, 1));

modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotation, 0, 0, 1);

effect.transform.modelviewMatrix = modelMatrix;
effect.transform.projectionMatrix = scene.projection;

One other note is that my sprite is on a texture alias. If i take out my rotation my sprite draws correctly centered under my finger. My project matrix is GLKMatrix4MakeOrtho(0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame), 0, 1, -1); so it matches the UIkit and the view its embedded in.


Solution

  • I ended up having to add a little more math to calculate additional offsets before i rotate.

    // lets adjust for our location based on our anchor point.
    GLKVector2 adjustment = GLKVector2Make(self.spriteSize.width * self.anchorPoint.x, 
                                           self.spriteSize.height * self.anchorPoint.y);
    
    // we need to further adjust based on our so we can calucate the adjust based on our anchor point in our image.
    GLKVector2 angleAdjustment;
    
    angleAdjustment.x = adjustment.x * cos(self.rotation) - adjustment.y * sin(self.rotation);
    angleAdjustment.y = adjustment.x * sin(self.rotation) + adjustment.y * cos(self.rotation);
    
    // now create our real position.
    GLKVector2 adjustedPosition = GLKVector2Subtract(self.position, angleAdjustment);
    GLKMatrix4 modelMatrix = GLKMatrix4Multiply(GLKMatrix4MakeTranslation(adjustedPosition.x, adjustedPosition.y, 1.0), GLKMatrix4MakeScale(adjustedScale.x, adjustedScale.y, 1));
    
    modelMatrix = GLKMatrix4Rotate(modelMatrix, self.rotation, 0, 0, 1);
    

    This will create an additional adjustment based on where in the image we want to rotate and then transform based on that. This works like a charm..