Skip to content

Commit

Permalink
Improved CCTransformationNode
Browse files Browse the repository at this point in the history
  • Loading branch information
Birkemose committed Jun 18, 2014
1 parent 8017785 commit 26939a3
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 22 deletions.
1 change: 1 addition & 0 deletions Extensions/CCTransformationNode/CCTransformationNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

@property (nonatomic, assign) float roll;
@property (nonatomic, assign) float pitch;
@property (nonatomic, assign) float yaw;
@property (nonatomic, assign) float perspective; // strength of the 3D perspective

@property (nonatomic, readonly, getter = isBackFacing) BOOL backFacing; // node is backfacing
Expand Down
80 changes: 69 additions & 11 deletions Extensions/CCTransformationNode/CCTransformationNode.m
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ - (instancetype)init
// initialize
_roll = 0.0f;
_pitch = 0.0f;
_yaw = 0.0f;
_perspective = 1.0;
_dirty = YES;
// done
Expand All @@ -59,17 +60,40 @@ - (instancetype)init

- (void)visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentTransform
{
if (!_visible) return;

if (_dirty)
{

CGSize size = [CCDirector sharedDirector].viewSize;
float aspect = size.width / size.height;

// create rotation matrix
GLKMatrix4 matrixPitch = GLKMatrix4MakeXRotation(_pitch);
GLKMatrix4 matrixRoll = GLKMatrix4MakeYRotation(_roll);
_transformation = GLKMatrix4Multiply(matrixRoll, matrixPitch);

// apple perspective
_transformation.m03 = _perspective * sinf(_roll) * cosf(_pitch);
_transformation.m13 = _perspective * sinf(_pitch) * cosf(_roll);
GLKMatrix4 matrixYaw = GLKMatrix4MakeZRotation(_yaw);

// create translation matrix
CGPoint pos = [self positionInPoints];
pos = ccp((2 * pos.x / size.width) - 1.0, (2 * pos.y / size.height) - 1.0);
GLKMatrix4 matrixTranslate = GLKMatrix4MakeTranslation(pos.x, pos.y, 0);

// greate perspective matrix
GLKMatrix4 perspective = GLKMatrix4Make(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, _perspective,
0.0, 0.0, 0.0, 1.0
);

// calculate combined rotation
GLKMatrix4 rotation = GLKMatrix4Multiply(matrixRoll, matrixPitch);

// adjust perspective for yaw and translation
perspective = GLKMatrix4Multiply(matrixYaw, perspective);
perspective = GLKMatrix4Multiply(matrixTranslate, perspective);

// create final rotation + perspective martix
_transformation = GLKMatrix4Multiply(perspective, rotation);

// transformation is up to date
_dirty = NO;
Expand All @@ -78,17 +102,45 @@ - (void)visit:(CCRenderer *)renderer parentTransform:(const GLKMatrix4 *)parentT
// calculate final transformation (used for backface calculation)
_finalTransformation = GLKMatrix4Multiply(_transformation, *parentTransform);

[super visit:renderer parentTransform:&_finalTransformation];
// create basic transformation matrix
// position is not used
CGAffineTransform t = [self nodeToParentTransform];
t.tx = [CCDirector sharedDirector].viewSize.width / 2;
t.ty = [CCDirector sharedDirector].viewSize.height / 2;

// Convert to 4x4 column major GLK matrix.
_finalTransformation = GLKMatrix4Multiply(_finalTransformation,
GLKMatrix4Make(
t.a, t.b, 0.0f, 0.0f,
t.c, t.d, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
t.tx, t.ty, _vertexZ, 1.0f
));

// draw self and children
BOOL drawn = NO;

for (CCNode *child in _children)
{
if (!drawn && (child.zOrder >= 0))
{
[self draw:renderer transform:&_finalTransformation];
drawn = YES;
}
[child visit:renderer parentTransform:&_finalTransformation];
}

if (!drawn) [self draw:renderer transform:&_finalTransformation];

// reset for next frame
_orderOfArrival = 0;
}

//----------------------------------------------------------------------

- (BOOL)isBackFacing
{
// this can not be calculated uder _dirty, as parent transform might change
GLKVector3 vector = (GLKVector3){0,0,1};
vector = GLKMatrix4MultiplyVector3 (_finalTransformation, vector);
return(vector.z > 0);
return(_finalTransformation.m23 > 0);
}

//----------------------------------------------------------------------
Expand All @@ -105,6 +157,12 @@ - (void)setPitch:(float)pitch
_pitch = pitch;
}

- (void)setYaw:(float)yaw
{
_dirty = YES;
_yaw = yaw;
}

//----------------------------------------------------------------------

@end
Expand Down
6 changes: 3 additions & 3 deletions Extensions/CCTransformationNode/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ CCTransformationNode
====================

Type of class : Descendant of CCNode

Uses extension : <NONE>
Uses extension : [NONE]

A node, capable of adding 3D transformations to a scene.

Expand All @@ -17,10 +16,11 @@ It requires no other setup, or that you switch to 3D. You can either add this no
Three properties have been implememnted.
1) Roll, which will roll the sprite around its Y axis
2) Pitch, which will roll the sprite around its X axis
3) Yaw, which will roll the sprite around its Z axis
3) Perspective, which will define the amount of perspective added (0=no perspective)

OBS!
**This component is still experimental**
There is still a slight problem with aspect ratio
The goal is to try to avoid to have the user to switch to a perspective projection, as this can cause artifacts for 2D games.


Expand Down
17 changes: 9 additions & 8 deletions cocos2d-iphone-ext/Classes/Tests/CCTransformationNodeTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,11 @@ - (void)cardFlipTest

_transformation.positionType = CCPositionTypeNormalized;
_transformation.position = ccp(0.5, 0.5);

[self.contentNode addChild:_transformation];

_card = [cardNode cardWithName:[cardNode randomCardName]];
_card.scale = 2;
// _card.scale = 2;
_card.name = @"card.0";
[_transformation addChild:_card];
}
Expand All @@ -90,22 +91,21 @@ - (void)cardFlipTest

- (void)cardFlipTestA
{
self.subTitle = @"(pitch + rotation) works";
self.subTitle = @"Pitch + Rotation";
_flipType = CCFlipTypePitchRotation;
[self cardFlipTest];
}

- (void)cardFlipTestB
{
self.subTitle = @"(roll + rotation) works";
self.subTitle = @"Roll + Rotation";
_flipType = CCFlipTypeRollRotation;
[self cardFlipTest];
}


- (void)cardFlipTestC
{
self.subTitle = @"(pitch + roll) BROKEN (wrong aspect 50% of the time)";
self.subTitle = @"Pitch + Roll";
_flipType = CCFlipTypePitchRoll;
[self cardFlipTest];
}
Expand All @@ -117,7 +117,6 @@ - (void)update:(CCTime)delta
delta *= 0.125;

CCNode *card = [self getChildByName:@"card.0" recursively:YES];
// card.rotation += 0.2;

if ([card isKindOfClass:[cardNode class]])
{
Expand All @@ -132,12 +131,14 @@ - (void)update:(CCTime)delta

case CCFlipTypePitchRotation:
_transformation.pitch += 11.0 * delta;
_transformation.rotation += 100 * delta;
// _transformation.rotation += 100 * delta;
_transformation.yaw += delta;
break;

case CCFlipTypeRollRotation:
_transformation.roll += 11.0 * delta;
_transformation.rotation += 100 * delta;
// _transformation.rotation += 100 * delta;
_transformation.yaw += delta;
break;
}
}
Expand Down

0 comments on commit 26939a3

Please sign in to comment.