コード例 #1
0
CollisionFeature::CollisionFeature(const std::vector<Coordinate> &line, const Anchor &anchor,
        const float top, const float bottom, const float left, const float right,
        const float boxScale, const float padding, const bool alongLine, const bool straight) {

    if (top == 0 && bottom == 0 && left == 0 && right == 0) return;

    const float y1 = top * boxScale - padding;
    const float y2 = bottom * boxScale + padding;
    const float x1 = left * boxScale - padding;
    const float x2 = right * boxScale + padding;

    if (alongLine) {
        float height = y2 - y1;
        const float length = x2 - x1;

        if (height <= 0.0f) return;

        height = std::max(10.0f * boxScale, height);

        Coordinate anchorPoint(int16_t(anchor.x), int16_t(anchor.y));

        if (straight) {
            // used for icon labels that are aligned with the line, but don't curve along it
            const vec2<double> vector = util::unit(vec2<double>(line[anchor.segment + 1] - line[anchor.segment])) * length;
            const std::vector<Coordinate> newLine({ anchorPoint - vector, anchorPoint + vector });
            bboxifyLabel(newLine, anchorPoint, 0, length, height);
        } else {
            // used for text labels that curve along a line
            bboxifyLabel(line, anchorPoint, anchor.segment, length, height);
        }
    } else {
        boxes.emplace_back(anchor, x1, y1, x2, y2, std::numeric_limits<float>::infinity());
    }
}
コード例 #2
0
/* \reimp (GraphicsLayer.h)
*/
void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
{
    if (value == anchorPoint())
        return;
    GraphicsLayer::setAnchorPoint(value);
    notifyChange(TextureMapperLayer::AnchorPointChange);
}
コード例 #3
0
void WebGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
{
    if (anchorPoint() == p)
        return;

    GraphicsLayer::setAnchorPoint(p);
    notifyChange();
}
コード例 #4
0
void WebGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
{
    if (anchorPoint() == p)
        return;

    GraphicsLayer::setAnchorPoint(p);
    didChangeGeometry();
}
コード例 #5
0
void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
{
    if (anchorPoint() == p)
        return;

    GraphicsLayer::setAnchorPoint(p);
    m_layerState.anchorPointChanged = true;
    didChangeGeometry();
}
コード例 #6
0
void WebGraphicsLayer::computeTransformedVisibleRect()
{
    if (!m_shouldUpdateVisibleRect)
        return;
    m_shouldUpdateVisibleRect = false;
    m_layerTransform.setLocalTransform(transform());
    m_layerTransform.setPosition(position());
    m_layerTransform.setAnchorPoint(anchorPoint());
    m_layerTransform.setSize(size());
    m_layerTransform.setFlattening(!preserves3D());
    m_layerTransform.setChildrenTransform(childrenTransform());
    m_layerTransform.combineTransforms(parent() ? toWebGraphicsLayer(parent())->m_layerTransform.combinedForChildren() : TransformationMatrix());

    // The combined transform will be used in tiledBackingStoreVisibleRect.
    adjustVisibleRect();
    adjustContentsScale();
}
コード例 #7
0
void WebGraphicsLayer::syncCompositingStateForThisLayerOnly()
{
    if (!m_layerTreeTileClient)
        m_layerTreeTileClient = layerTreeTileClient();

    updateContentBuffers();

    if (!m_modified)
        return;

    m_layerInfo.name = name();
    m_layerInfo.anchorPoint = anchorPoint();
    m_layerInfo.backfaceVisible = backfaceVisibility();
    m_layerInfo.childrenTransform = childrenTransform();
    m_layerInfo.contentsOpaque = contentsOpaque();
    m_layerInfo.contentsRect = contentsRect();
    m_layerInfo.drawsContent = drawsContent();
    m_layerInfo.mask = toWebLayerID(maskLayer());
    m_layerInfo.masksToBounds = masksToBounds();
    m_layerInfo.opacity = opacity();
    m_layerInfo.parent = toWebLayerID(parent());
    m_layerInfo.pos = position();
    m_layerInfo.preserves3D = preserves3D();
    m_layerInfo.replica = toWebLayerID(replicaLayer());
    m_layerInfo.size = size();
    m_layerInfo.transform = transform();
    m_contentNeedsDisplay = false;
    m_layerInfo.children.clear();

    for (size_t i = 0; i < children().size(); ++i)
        m_layerInfo.children.append(toWebLayerID(children()[i]));

    ASSERT(m_layerTreeTileClient);
    if (m_layerInfo.imageIsUpdated && m_image && !m_layerInfo.imageBackingStoreID)
        m_layerInfo.imageBackingStoreID = m_layerTreeTileClient->adoptImageBackingStore(m_image.get());

    m_layerTreeTileClient->didSyncCompositingStateForLayer(m_layerInfo);
    m_modified = false;
    m_layerInfo.imageIsUpdated = false;
    if (m_hasPendingAnimations)
        notifyAnimationStarted(WTF::currentTime());
    m_layerInfo.animations.clear();
    m_hasPendingAnimations = false;
}
コード例 #8
0
void WebGraphicsLayer::syncLayerState()
 {
    if (!m_shouldSyncLayerState)
        return;
    m_shouldSyncLayerState = false;

    m_layerInfo.anchorPoint = anchorPoint();
    m_layerInfo.backfaceVisible = backfaceVisibility();
    m_layerInfo.childrenTransform = childrenTransform();
    m_layerInfo.contentsOpaque = contentsOpaque();
    m_layerInfo.contentsRect = contentsRect();
    m_layerInfo.drawsContent = drawsContent();
    m_layerInfo.mask = toWebLayerID(maskLayer());
    m_layerInfo.masksToBounds = masksToBounds();
    m_layerInfo.opacity = opacity();
    m_layerInfo.parent = toWebLayerID(parent());
    m_layerInfo.pos = position();
    m_layerInfo.preserves3D = preserves3D();
    m_layerInfo.replica = toWebLayerID(replicaLayer());
    m_layerInfo.size = size();
    m_layerInfo.transform = transform();
    m_webGraphicsLayerClient->syncLayerState(m_id, m_layerInfo);
}
コード例 #9
0
void GraphicsLayerTextureMapper::commitLayerChanges()
{
    if (m_changeMask == NoChanges)
        return;

    if (m_changeMask & ChildrenChange) {
        Vector<TextureMapperLayer*> textureMapperLayerChildren;
        toTextureMapperLayerVector(children(), textureMapperLayerChildren);
        m_layer->setChildren(textureMapperLayerChildren);
    }

    if (m_changeMask & MaskLayerChange)
        m_layer->setMaskLayer(toTextureMapperLayer(maskLayer()));

    if (m_changeMask & ReplicaLayerChange)
        m_layer->setReplicaLayer(toTextureMapperLayer(replicaLayer()));

    if (m_changeMask & PositionChange)
        m_layer->setPosition(position());

    if (m_changeMask & AnchorPointChange)
        m_layer->setAnchorPoint(anchorPoint());

    if (m_changeMask & SizeChange)
        m_layer->setSize(size());

    if (m_changeMask & TransformChange)
        m_layer->setTransform(transform());

    if (m_changeMask & ChildrenTransformChange)
        m_layer->setChildrenTransform(childrenTransform());

    if (m_changeMask & Preserves3DChange)
        m_layer->setPreserves3D(preserves3D());

    if (m_changeMask & ContentsRectChange)
        m_layer->setContentsRect(contentsRect());

    if (m_changeMask & MasksToBoundsChange)
        m_layer->setMasksToBounds(masksToBounds());

    if (m_changeMask & DrawsContentChange)
        m_layer->setDrawsContent(drawsContent());

    if (m_changeMask & ContentsVisibleChange)
        m_layer->setContentsVisible(contentsAreVisible());

    if (m_changeMask & ContentsOpaqueChange)
        m_layer->setContentsOpaque(contentsOpaque());

    if (m_changeMask & BackfaceVisibilityChange)
        m_layer->setBackfaceVisibility(backfaceVisibility());

    if (m_changeMask & OpacityChange)
        m_layer->setOpacity(opacity());

    if (m_changeMask & BackgroundColorChange)
        m_layer->setSolidColor(solidColor());

#if ENABLE(CSS_FILTERS)
    if (m_changeMask & FilterChange)
        m_layer->setFilters(filters());
#endif

    if (m_changeMask & BackingStoreChange)
        m_layer->setBackingStore(m_backingStore);

    if (m_changeMask & DebugVisualsChange)
        m_layer->setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());

    if (m_changeMask & RepaintCountChange)
        m_layer->setRepaintCount(repaintCount());

    if (m_changeMask & ContentChange)
        m_layer->setContentsLayer(platformLayer());

    if (m_changeMask & AnimationChange)
        m_layer->setAnimations(m_animations);

    if (m_changeMask & AnimationStarted)
        client()->notifyAnimationStarted(this, m_animationStartTime);

    if (m_changeMask & FixedToViewporChange)
        m_layer->setFixedToViewport(fixedToViewport());

    if (m_changeMask & IsScrollableChange)
        m_layer->setIsScrollable(isScrollable());

    if (m_changeMask & CommittedScrollOffsetChange)
        m_layer->didCommitScrollOffset(m_committedScrollOffset);

    m_changeMask = NoChanges;
}
コード例 #10
0
ファイル: main.cpp プロジェクト: MR-KO/GAGT
/*
 * Load a given world, i.e. read the world from the `levels' data structure and
 * convert it into a Box2D world.
 */
void load_world(unsigned int level) {
	// Pause the game when loading a new level
	play = 0;

	if (level >= num_levels) {
		// Note that level is unsigned but we still use %d so -1 is shown as
		// such.
		printf("Warning: level %d does not exist.\n", level);
		return;
	}

	// Create a Box2D world and populate it with all bodies for this level
	// (including the ball).
	current_level = level + 1;
	cur_level = &(levels[level]);
	init(cur_level->num_joints);
	b2Vec2 gravity (0, -9.81);
	bool do_sleep = true;

	world = new b2World(gravity);
	world->SetAllowSleeping(do_sleep);

	// printf("num_polygons = %i\n", levels[0].num_polygons);
	// printf("is_Dynamic = %d\n", levels[0].polygons[0].is_dynamic);

	// Create ground
	b2BodyDef groundBodyDef;
	groundBodyDef.position.Set(0.0f, -world_y / 2);
	ground = world->CreateBody(&groundBodyDef);

	// addBodyToCreatedBodies(ground, num_created_bodies++);

	b2PolygonShape groundBox;
	groundBox.SetAsBox(world_x, world_y / 2);
	ground->CreateFixture(&groundBox, 0.0f);

	// Setup rest of level.
	for (unsigned int i = 0; i < cur_level->num_polygons; i++) {
		b2Vec2 *vertices = new b2Vec2[cur_level->polygons[i].num_verts];

		for (unsigned int j = 0; j < cur_level->polygons[i].num_verts; j ++) {
			vertices[j].Set(cur_level->polygons[i].verts[j].x, cur_level->polygons[i].verts[j].y);
		}

		makePolygon(cur_level->polygons[i].is_dynamic, cur_level->polygons[i].position.x,
			cur_level->polygons[i].position.y, vertices, cur_level->polygons[i].num_verts,
			num_created_bodies++);

		delete[] vertices;
	}

	// Create ball
	b2BodyDef ballBodyDef;
	ballBodyDef.type = b2_dynamicBody;
	ballBodyDef.position.Set(cur_level->start.x, cur_level->start.y);
	ball = world->CreateBody(&ballBodyDef);

	b2CircleShape dynamicCircle;
	dynamicCircle.m_radius = ball_radius;

	b2FixtureDef fixtureDef;
	fixtureDef.shape = &dynamicCircle;
	fixtureDef.density = 1.0f;
	fixtureDef.friction = 0.3f;
	ball->CreateFixture(&fixtureDef);

	// Setup joints.
	for (unsigned int i = 0; i < cur_level->num_joints; i++) {
		if (cur_level->joints[i].joint_type == JOINT_REVOLUTE) {
			b2RevoluteJointDef jointDef;
			// jointDef.anchorPoint = objectA->GetPosition();
			b2Body *objectA = created_bodies[cur_level->joints[i].objectA];
			b2Body *objectB = created_bodies[cur_level->joints[i].objectB];

			b2Vec2 anchorPoint(cur_level->joints[i].anchor.x,
				cur_level->joints[i].anchor.y);
			jointDef.Initialize(objectA, objectB, anchorPoint);

			world->CreateJoint(&jointDef);
		}

		else if (cur_level->joints[i].joint_type == JOINT_PULLEY) {
			b2Vec2 anchorPoint1(cur_level->joints[i].anchor.x, cur_level->joints[i].anchor.x);
			b2Vec2 anchorPoint2(cur_level->joints[i].pulley.anchor2.x, cur_level->joints[i].pulley.anchor2.x);
			b2Vec2 groundAnchor1(cur_level->joints[i].pulley.ground1.x, cur_level->joints[i].pulley.ground1.y);
			b2Vec2 groundAnchor2(cur_level->joints[i].pulley.ground2.x, cur_level->joints[i].pulley.ground2.y);
			float ratio = cur_level->joints[i].pulley.ratio;

			b2Body *objectA = created_bodies[cur_level->joints[i].objectA];
			b2Body *objectB = created_bodies[cur_level->joints[i].objectB];

			b2PulleyJointDef jointDef;
			jointDef.Initialize(objectA, objectB, groundAnchor1, groundAnchor2, anchorPoint1, anchorPoint2, ratio);
			world->CreateJoint(&jointDef);
		}
	}
}
コード例 #11
0
ファイル: CCBillBoard.cpp プロジェクト: DominicD/Hyperdrive
bool BillBoard::calculateBillbaordTransform()
{
    //Get camera world position
    auto camera = Camera::getVisitingCamera();
    const Mat4& camWorldMat = camera->getNodeToWorldTransform();
    
    //TODO: use math lib to calculate math lib Make it easier to read and maintain
    if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || memcmp(_mvTransform.m, _modelViewTransform.m, sizeof(float) * 16) != 0 || _modeDirty || true)
    {
        //Rotate based on anchor point
        Vec3 anchorPoint(_anchorPointInPoints.x , _anchorPointInPoints.y , 0.0f);
        Mat4 localToWorld = _modelViewTransform;
        localToWorld.translate(anchorPoint);
        
        //Decide billboard mode
        Vec3 camDir;
        switch (_mode)
        {
            case Mode::VIEW_POINT_ORIENTED:
                camDir.set(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
                break;
            case Mode::VIEW_PLANE_ORIENTED:
                camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
                break;
            default:
                CCASSERT(false, "invalid billboard mode");
                break;
        }
        _modeDirty = false;
        
        if (camDir.length() < MATH_TOLERANCE)
        {
            camDir.set(camWorldMat.m[8], camWorldMat.m[9], camWorldMat.m[10]);
        }
        camDir.normalize();
        
        Quaternion rotationQuaternion;
        this->getNodeToWorldTransform().getRotation(&rotationQuaternion);
        
        Mat4 rotationMatrix;
        rotationMatrix.setIdentity();

        Vec3 upAxis(rotationMatrix.m[4],rotationMatrix.m[5],rotationMatrix.m[6]);
        Vec3 x, y;
        camWorldMat.transformVector(upAxis, &y);
        Vec3::cross(camDir, y, &x);
        x.normalize();
        Vec3::cross(x, camDir, &y);
        y.normalize();
        
        float xlen = sqrtf(localToWorld.m[0] * localToWorld.m[0] + localToWorld.m[1] * localToWorld.m[1] + localToWorld.m[2] * localToWorld.m[2]);
        float ylen = sqrtf(localToWorld.m[4] * localToWorld.m[4] + localToWorld.m[5] * localToWorld.m[5] + localToWorld.m[6] * localToWorld.m[6]);
        float zlen = sqrtf(localToWorld.m[8] * localToWorld.m[8] + localToWorld.m[9] * localToWorld.m[9] + localToWorld.m[10] * localToWorld.m[10]);
        
        Mat4 billboardTransform;
        
        billboardTransform.m[0] = x.x * xlen; billboardTransform.m[1] = x.y * xlen; billboardTransform.m[2] = x.z * xlen;
        billboardTransform.m[4] = y.x * ylen; billboardTransform.m[5] = y.y * ylen; billboardTransform.m[6] = y.z * ylen;
        billboardTransform.m[8] = -camDir.x * zlen; billboardTransform.m[9] = -camDir.y * zlen; billboardTransform.m[10] = -camDir.z * zlen;
        billboardTransform.m[12] = localToWorld.m[12]; billboardTransform.m[13] = localToWorld.m[13]; billboardTransform.m[14] = localToWorld.m[14];
        
        billboardTransform.translate(-anchorPoint);
        _mvTransform = _modelViewTransform = billboardTransform;
        
        _camWorldMat = camWorldMat;
        
        return true;
    }
    
    return false;
}
コード例 #12
0
ファイル: DisplayListItems.cpp プロジェクト: ollie314/webkit
void DrawGlyphs::apply(GraphicsContext& context) const
{
    FontCascade::drawGlyphs(context, m_font, generateGlyphBuffer(), 0, m_glyphs.size(), anchorPoint(), m_smoothingMode);
}
コード例 #13
0
void WKCACFLayer::printLayer(int indent) const
{
    CGPoint layerPosition = position();
    CGPoint layerAnchorPoint = anchorPoint();
    CGRect layerBounds = bounds();
    printIndent(indent);
    fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g]\n",
        isTransformLayer() ? "transform-layer" : "layer",
        layerPosition.x, layerPosition.y, zPosition(), 
        layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height,
        layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ());

    // Print name if needed
    String layerName = name();
    if (!layerName.isEmpty()) {
        printIndent(indent + 1);
        fprintf(stderr, "(name %s)\n", layerName.utf8().data());
    }

    // Print masksToBounds if needed
    bool layerMasksToBounds = masksToBounds();
    if (layerMasksToBounds) {
        printIndent(indent + 1);
        fprintf(stderr, "(masksToBounds true)\n");
    }

    // Print opacity if needed
    float layerOpacity = opacity();
    if (layerOpacity != 1) {
        printIndent(indent + 1);
        fprintf(stderr, "(opacity %hf)\n", layerOpacity);
    }

    // Print sublayerTransform if needed
    CATransform3D layerTransform = sublayerTransform();
    if (!CATransform3DIsIdentity(layerTransform)) {
        printIndent(indent + 1);
        fprintf(stderr, "(sublayerTransform ");
        printTransform(layerTransform);
        fprintf(stderr, ")\n");
    }

    // Print transform if needed
    layerTransform = transform();
    if (!CATransform3DIsIdentity(layerTransform)) {
        printIndent(indent + 1);
        fprintf(stderr, "(transform ");
        printTransform(layerTransform);
        fprintf(stderr, ")\n");
    }

    // Print contents if needed
    CGImageRef layerContents = contents();
    if (layerContents) {
        printIndent(indent + 1);
        fprintf(stderr, "(contents (image [%d %d]))\n",
            CGImageGetWidth(layerContents), CGImageGetHeight(layerContents));
    }

    // Print sublayers if needed
    int n = numSublayers();
    if (n > 0) {
        printIndent(indent + 1);
        fprintf(stderr, "(sublayers\n");
        for (int i = 0; i < n; ++i)
            sublayerAtIndex(i)->printLayer(indent + 2);

        printIndent(indent + 1);
        fprintf(stderr, ")\n");
    }

    printIndent(indent);
    fprintf(stderr, ")\n");
}
コード例 #14
0
ファイル: CCBillBoard.cpp プロジェクト: TheWindShan/HYFish
void BillBoard::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
{
    auto camera = Camera::getVisitingCamera();
    const Mat4& camWorldMat = camera->getNodeToWorldTransform();
    if (memcmp(_camWorldMat.m, camWorldMat.m, sizeof(float) * 16) != 0 || memcmp(_mvTransform.m, transform.m, sizeof(float) * 16) != 0 || _modeDirty)
    {
        Vec3 anchorPoint(_anchorPointInPoints.x , _anchorPointInPoints.y , 0.0f);
        Mat4 localToWorld = transform;
        localToWorld.translate(anchorPoint);
        Vec3 camDir;
        switch (_mode)
        {
        case Mode::VIEW_POINT_ORIENTED:
            camDir = Vec3(localToWorld.m[12] - camWorldMat.m[12], localToWorld.m[13] - camWorldMat.m[13], localToWorld.m[14] - camWorldMat.m[14]);
            break;
        case Mode::VIEW_PLANE_ORIENTED:
            camWorldMat.transformVector(Vec3(0.0f, 0.0f, -1.0f), &camDir);
            break;
        default:
                CCASSERT(false, "invalid billboard mode");
            break;
        }
        _modeDirty = false;
        if (camDir.length() < MATH_TOLERANCE)
        {
            camDir.set(camWorldMat.m[8], camWorldMat.m[9], camWorldMat.m[10]);
        }
        camDir.normalize();
        Quaternion rotationQuaternion;
        this->getNodeToWorldTransform().getRotation(&rotationQuaternion);
        // fetch the rotation angle of z
        float rotationZ = atan2(2*(rotationQuaternion.w*rotationQuaternion.z + rotationQuaternion.x*rotationQuaternion.y),
            (1 - 2* (rotationQuaternion.y*rotationQuaternion.y + rotationQuaternion.z *rotationQuaternion.z)));
        Mat4 rotationMatrix;
        rotationMatrix.setIdentity();
        rotationMatrix.rotateZ(rotationZ);
        Vec3 upAxis = Vec3(rotationMatrix.m[4],rotationMatrix.m[5],rotationMatrix.m[6]);
        Vec3 x, y;
        camWorldMat.transformVector(upAxis, &y);
        Vec3::cross(camDir, y, &x);
        x.normalize();
        Vec3::cross(x, camDir, &y);
        y.normalize();

        float xlen = sqrtf(localToWorld.m[0] * localToWorld.m[0] + localToWorld.m[1] * localToWorld.m[1] + localToWorld.m[2] * localToWorld.m[2]);
        float ylen = sqrtf(localToWorld.m[4] * localToWorld.m[4] + localToWorld.m[5] * localToWorld.m[5] + localToWorld.m[6] * localToWorld.m[6]);
        float zlen = sqrtf(localToWorld.m[8] * localToWorld.m[8] + localToWorld.m[9] * localToWorld.m[9] + localToWorld.m[10] * localToWorld.m[10]);

        _billboardTransform.m[0] = x.x * xlen; _billboardTransform.m[1] = x.y * xlen; _billboardTransform.m[2] = x.z * xlen;
        _billboardTransform.m[4] = y.x * ylen; _billboardTransform.m[5] = y.y * ylen; _billboardTransform.m[6] = y.z * ylen;
        _billboardTransform.m[8] = -camDir.x * zlen; _billboardTransform.m[9] = -camDir.y * zlen; _billboardTransform.m[10] = -camDir.z * zlen;
        _billboardTransform.m[12] = localToWorld.m[12]; _billboardTransform.m[13] = localToWorld.m[13]; _billboardTransform.m[14] = localToWorld.m[14];

        _billboardTransform.translate(-anchorPoint);

        const Mat4 &viewMat = camWorldMat.getInversed();
        _zDepthInView = -(viewMat.m[2] * _billboardTransform.m[12] + viewMat.m[6] * _billboardTransform.m[13] + viewMat.m[10] * _billboardTransform.m[14] + viewMat.m[14]);
        _mvTransform = transform;
        _camWorldMat = camWorldMat;
    }

    //FIXME: frustum culling here
    {
        _quadCommand.init(_zDepthInView, _texture->getName(), getGLProgramState(), _blendFunc, &_quad, 1, _billboardTransform);
        _quadCommand.setTransparent(true);
        renderer->addCommand(&_quadCommand);
    }
}
コード例 #15
0
ファイル: CCNode.cpp プロジェクト: 2youyou2/cocos2d-x-lite
const Mat4& Node::getNodeToParentTransform() const
{
    if (_transformDirty)
    {
        // Translate values
        float x = _position.x;
        float y = _position.y;
        float z = _positionZ;

        if (_ignoreAnchorPointForPosition)
        {
            x += _anchorPointInPoints.x;
            y += _anchorPointInPoints.y;
        }

        bool needsSkewMatrix = ( _skewX || _skewY );


        Vec2 anchorPoint(_anchorPointInPoints.x * _scaleX, _anchorPointInPoints.y * _scaleY);

        // calculate real position
        if (! needsSkewMatrix && !_anchorPointInPoints.isZero())
        {
            x += -anchorPoint.x;
            y += -anchorPoint.y;
        }

        // Build Transform Matrix = translation * rotation * scale
        Mat4 translation;
        //move to anchor point first, then rotate
        Mat4::createTranslation(x + anchorPoint.x, y + anchorPoint.y, z, &translation);

        Mat4::createRotation(_rotationQuat, &_transform);

        if (_rotationZ_X != _rotationZ_Y)
        {
            // Rotation values
            // Change rotation code to handle X and Y
            // If we skew with the exact same value for both x and y then we're simply just rotating
            float radiansX = -CC_DEGREES_TO_RADIANS(_rotationZ_X);
            float radiansY = -CC_DEGREES_TO_RADIANS(_rotationZ_Y);
            float cx = cosf(radiansX);
            float sx = sinf(radiansX);
            float cy = cosf(radiansY);
            float sy = sinf(radiansY);

            float m0 = _transform.m[0], m1 = _transform.m[1], m4 = _transform.m[4], m5 = _transform.m[5], m8 = _transform.m[8], m9 = _transform.m[9];
            _transform.m[0] = cy * m0 - sx * m1, _transform.m[4] = cy * m4 - sx * m5, _transform.m[8] = cy * m8 - sx * m9;
            _transform.m[1] = sy * m0 + cx * m1, _transform.m[5] = sy * m4 + cx * m5, _transform.m[9] = sy * m8 + cx * m9;
        }
        _transform = translation * _transform;
        //move by (-anchorPoint.x, -anchorPoint.y, 0) after rotation
        _transform.translate(-anchorPoint.x, -anchorPoint.y, 0);


        if (_scaleX != 1.f)
        {
            _transform.m[0] *= _scaleX, _transform.m[1] *= _scaleX, _transform.m[2] *= _scaleX;
        }
        if (_scaleY != 1.f)
        {
            _transform.m[4] *= _scaleY, _transform.m[5] *= _scaleY, _transform.m[6] *= _scaleY;
        }
        if (_scaleZ != 1.f)
        {
            _transform.m[8] *= _scaleZ, _transform.m[9] *= _scaleZ, _transform.m[10] *= _scaleZ;
        }

        // FIXME:: Try to inline skew
        // If skew is needed, apply skew and then anchor point
        if (needsSkewMatrix)
        {
            float skewMatArray[16] =
            {
                1, (float)tanf(CC_DEGREES_TO_RADIANS(_skewY)), 0, 0,
                (float)tanf(CC_DEGREES_TO_RADIANS(_skewX)), 1, 0, 0,
                0,  0,  1, 0,
                0,  0,  0, 1
            };
            Mat4 skewMatrix(skewMatArray);

            _transform = _transform * skewMatrix;

            // adjust anchor point
            if (!_anchorPointInPoints.isZero())
            {
                // FIXME:: Argh, Mat4 needs a "translate" method.
                // FIXME:: Although this is faster than multiplying a vec4 * mat4
                _transform.m[12] += _transform.m[0] * -_anchorPointInPoints.x + _transform.m[4] * -_anchorPointInPoints.y;
                _transform.m[13] += _transform.m[1] * -_anchorPointInPoints.x + _transform.m[5] * -_anchorPointInPoints.y;
            }
        }

        if (_useAdditionalTransform)
        {
            _transform = _transform * _additionalTransform;
        }

        _transformDirty = false;
    }

    return _transform;
}