Cocos convertToWorldSpace 引數詳解

bloodsuckerccj發表於2017-06-07

convertToWorldSpace 引數詳解

發表於2016/8/19 11:21:31  160人閱讀

分類: cocos2d-x

關於這個函式作用大家都知道,是把本地座標轉換為世界座標,但是這種說法太寬泛。到底什麼是本地座標,什麼是世界座標,這個函式的用法 :

node->convertToWorldSpace(child->getPosition)  用的時候這個node和child到底是什麼東西?


工作中有一個需求是判斷子彈是否飛出了螢幕,但是子彈是在地圖層的,地圖又在gameLayer層上,gameLayer上又有層,這一層套一層到底該怎麼判斷子彈的絕對位置呢?

bullet->getPosition() 查了下資料得到的位置是相對父結點的,即地圖層下的區域性座標,我希望得到是子彈相對於螢幕左下角的位置,這也就是著名的絕對座標。顯然bullet->getPosition()在地圖一移動的情況下就不再是世界座標了,那可怎麼辦呢?

網上很多網友給出的解決辦法是座標系轉換,即本地座標轉為世界座標系,就一句程式碼就行:

posBullet = (bullet->getParent())->convertToWorldSpace(bullet->getPosition());

經試驗是可行的,但我對此深深的懷疑:bullet的父結點是一層套一層的,那convertToWorldSpace裡的引數是什麼意思,(bullet->getParent())又是什麼,為什麼不能是(bullet->getParent()->getParent())

看了很多官方說法,再查原始碼:終於理解了這方法的含義:我們是要求的是bullet的世界座標系,即相對於螢幕左下角的座標,所以convertToWorldSpace的引數是 bullet->getPosition(),那什麼執行主體是bullet->getParent()而不用考慮更深層次的父結點呢,原因很簡單,bullet的position是相對於它的父結點的,也就是bullet->getParent(),所以執行主體也就是bullet->getParent(),那怎麼保證此函式求到的是最上層的世界座標而不是相對於他的父結點的座標呢,看原始碼:

Vec2 Node::convertToWorldSpace(const Vec2& nodePoint) const
{
    Mat4 tmp = getNodeToWorldTransform();
    Vec3 vec3(nodePoint.x, nodePoint.y, 0);
    Vec3 ret;
    tmp.transformPoint(vec3,&ret);
    return Vec2(ret.x, ret.y);
}


裡面有個重要的矩陣變換 getNodeToWorldTransform() ,估且不要理解其中複雜的數學變換,它的原始碼:

Mat4 Node::getNodeToWorldTransform() const
{
    Mat4 t = this->getNodeToParentTransform();


    for (Node *p = _parent; p != nullptr; p = p->getParent())
    {
        t = p->getNodeToParentTransform() * t;
    }

    return t;
}

可看出它是一層一層向上回溯找其父結點的變換矩陣的,所以最後能求到最上層父結點的變換矩陣,也就求得了世界座標系。所以

posBullet = (bullet->getParent())->convertToWorldSpace(bullet->getPosition()); 此方法是正確的