COCOS2DX坐标转换

游戏中经常会用到一些变换:

游戏中武器和角色在一个layer上,为了效率,会考虑将bullet, effect和 PhysicsParticle分别放到不用的层上,对应的层上使用batchnode来提高效率

武器和PhysicsParticleLauncher(粒子发射器)绑定,发射的时候,会向PhysicsParticleLayer的武器相同的位置上生成一个物理粒子特效

 

会经常用到convertToNodeSpace和convertToWorldSpace转换坐标

我们加三个sprite,r0,r1,r2,

r0的父节点是layer, 父节点下坐标(0,0,100,100)

r1的父节点是r0,父节点下坐标(0,0,100,100)

r2的父节点是r1,父节点下坐标(0,0,100,20)

 

bool HelloWorld::init()  
{  
    //  
    // 1. super init first  
    if ( !Layer::init() ) {  
        return false;  
    }  
      
    // r0加入到根节点上(Layer) 坐标(0,0)  
    Sprite* r0 = Sprite::create("data/pic/gun.png");  
    r0->setAnchorPoint(Point(0.f, 0.f));  
    this->addChild(r0);  
      
    // r1加入到r0上  
    Sprite* r1 = Sprite::create("data/pic/gun.png");  
    r1->setAnchorPoint(Point(0.f, 0.f));  
    r1->setPosition(Point(100, 0));  
    r0->addChild(r1);  
      
    // r2加入到r1上  
    Sprite* r2 = Sprite::create("data/pic/gun.png");  
    r2->setAnchorPoint(Point(0.f, 0.f));  
    r2->setPosition(Point(100, 20));  
    r1->addChild(r2);  
      
}  

如何将r2的坐标转换为世界坐标?

如何将r2的坐标转换为r0的局部坐标?

// 获得r2的世界坐标,两种方法  
// 方法1:以r2坐标系为起点,向根节点(世界坐标)变换,传的坐标是r2锚点所在r2的局部坐标  
// 如果锚点是(1,1),传的参数应该是Point(r2的宽度, r2的高度)
Point p2world = r2->convertToWorldSpace(Point(0, 0));  
  
// 方法2:以r1坐标系为起点,向根节点(世界坐标)变换,坐标为r2在父节点r1内的坐标  
p2world = r1->convertToWorldSpace(r2->getPosition());  
  
// 获得r2在r0坐标系中的坐标  
// convertToNodeSpace要传入的坐标为世界坐标  
Point pt = r0->convertToNodeSpace(p2world);  

 

 

 

方法如上:

工作原理详见cocos2dx代码

Point Node::convertToWorldSpace(const Point& nodePoint) const  
{  
    //获取位移变换矩阵,通过矩阵相乘代替向量加法来实现位移变换
    kmMat4 tmp = getNodeToWorldTransform();  
    kmVec3 vec3 = {nodePoint.x, nodePoint.y, 0};  
    kmVec3 ret;  
    kmVec3Transform(&ret, &vec3, &tmp);  
    return Point(ret.x, ret.y);  
  
}  
  
kmMat4 Node::getNodeToWorldTransform() const  
{  
    kmMat4 t = this->getNodeToParentTransform();  
  
    for (Node *p = _parent; p != nullptr; p = p->getParent())  
        kmMat4Multiply(&t, &p->getNodeToParentTransform(), &t);  
  
    return t;  
}

kmMat4 tmp = getNodeToWorldTransform(); 获得的矩阵类似这种形式:

\begin{bmatrix} 1 &0 &0 &tx \\ 0& 1 &0 & ty\\ 0& 0 &1 & tz\\ 0& 0 & 0 & 1\end{bmatrix}

因为:

\begin{bmatrix} x2\\ y2\\ z2\\ 1\end{bmatrix}=\begin{bmatrix} 1 &0 &0 &tx \\ 0& 1 &0 & ty\\ 0& 0 &1& tz\\ 0& 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x1\\ y1\\ z1\\ 1 \end{bmatrix}= \begin{bmatrix} x1+tx\\ y1+ty\\ z1+tz\\ 1\end{bmatrix}

/*

const Mat4 Mat4::IDENTITY = Mat4(
                    1.0f, 0.0f, 0.0f, 0.0f, --矩阵第一列的元素
                    0.0f, 1.0f, 0.0f, 0.0f, --矩阵第二列的元素
                    0.0f, 0.0f, 1.0f, 0.0f, --矩阵第三列的元素
                    0.0f, 0.0f, 0.0f, 1.0f);--矩阵第四列的元素
   在C++中用一个含有16个float元素的数组 表示4x4矩阵,按照列排序。数组下标对应元素位置:
    0  4  8   12
    1  5  9   13
    2  6  10  14
    3  7  11  15
*/

//用数组表示4x4矩阵,按照列排序
//下标0-3是第一列、4-7是第二列、8-11是第三列、12-15是第四列元素
const Mat4 Mat4::IDENTITY = Mat4(
                    1.0f, 0.0f, 0.0f, 0.0f, --矩阵第一列的元素
                    0.0f, 1.0f, 0.0f, 0.0f, --矩阵第二列的元素
                    0.0f, 0.0f, 1.0f, 0.0f, --矩阵第三列的元素
                    0.0f, 0.0f, 0.0f, 1.0f);--矩阵第四列的元素
void Mat4::createTranslation(float xTranslation, float yTranslation, float zTranslation, Mat4* dst)
{
    GP_ASSERT(dst);

    memcpy(dst, &IDENTITY, MATRIX_SIZE);
    /*
       1.0f, 0.0f, 0.0f, 0.0f,
       0.0f, 1.0f, 0.0f, 0.0f,
       0.0f, 0.0f, 1.0f, 0.0f,
         x,    y,   z,   1.0f
        矩阵数组中 x,y,z位置的元素(第四列)被重新赋值
    */
    dst->m[12] = xTranslation;
    dst->m[13] = yTranslation;
    dst->m[14] = zTranslation;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos 3D是一个用于开发3D游戏和应用程序的框架,它基于Cocos2d-x引擎。在Cocos 3D中,坐标系可以分为世界坐标系、模型坐标系和观察坐标系。 要将3D坐标转换为2D坐标,我们首先需要确定摄像机的位置和观察方向。通过设置摄像机的位置和方向,可以确定观察坐标系。然后,我们可以使用透视投影或正交投影来将3D场景投射到2D平面上。 在Cocos 3D中,可以使用Viewport(视口)和Camera(摄像机)来控制3D到2D的转换。视口决定了渲染的区域,而摄像机则定义了观察坐标系。 在代码中,可以通过以下步骤将3D坐标转换为2D坐标: 1. 创建一个Viewport,并设置它的大小和位置。 2. 创建一个Camera,并设置它的位置、观察目标和投影方式(透视或正交)。 3. 将需要转换的3D坐标传递给Camera的unproject方法。 unproject方法可以将3D坐标转换为在视口中的2D坐标。它将返回一个Vec3对象,其中包含在视口中的2D坐标。 以下是一个简单的示例代码,展示如何将3D坐标转换为2D坐标: ```cpp // 创建一个Viewport auto viewport = Viewport::create(0, 0, screenWidth, screenHeight); // 创建一个Camera auto camera = Camera::createPerspective(60, screenWidth / screenHeight, 0.1f, 1000); // 设置Camera的位置和观察目标 camera->setPosition3D(Vec3(0, 0, 10)); camera->lookAt(Vec3(0, 0, 0)); // 将3D坐标(1, 1, 1)转换为2D坐标 Vec3 worldPosition(1, 1, 1); Vec3 screenPosition = camera->unproject(viewport, worldPosition); // 打印转换后的2D坐标 CCLOG("2D坐标:(%f, %f)", screenPosition.x, screenPosition.y); ``` 通过以上步骤,我们可以将3D坐标转换为2D坐标,并将结果保存在screenPosition变量中。在示例中,我们将3D坐标(1, 1, 1)转换为2D坐标,并打印结果。 需要注意的是,3D坐标转换为2D坐标需要在渲染之前进行,因此最好在update或draw函数中进行转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值