cocos2dx矩阵坐标计算的坑用transformPoint 而不是 transformVector

本文讲述了在Cocos2d-x 3.0中重载Sprite的OnDraw函数时遇到的坐标计算问题,作者发现Mat4的transformPoint方法解决了原本transformVector和 *=运算无效的问题。文章还揭示了Cocos2d-x中部分坐标计算在CPU中进行的特点,并给出了自定义精灵坐标调整的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在重载Sprite 的 OnDraw()函数中 计算顶点坐标, 获取精灵的模型矩阵 乘以 quad 的顶点结果坐标

没发生任何改变, 原来是使用了Mat4的 transformVector 方法, 然后又发现Mat4的矩阵有重载 Vec3的  *= 运算符

,又用该运算符计算结果还是没有任何改变, 有点怀疑人生了。 后来又搜索Mat4中所有和Vec3相关的函数,发现

还有个transformPoint 方法。 试了一下居然成功了, 真坑啊, 仔细对比了一下和另外两个函数的区别, 原来 transformVector 和 *= 运算符

把 Vec3 转 Vec4的时候 第四个数补了0 , 而只有transformPoint是补的1 , 因此前两个函数没有生效。

 

另外发现Cocos2dx的一个小与众不同的地方: 部分顶点坐标的转化计算在cpu中进行

函数:CCRenderer.cpp 中  void Renderer::fillVerticesAndIndices(const TrianglesCommand* cmd)

改函数直接用modelView来在cpu中进行了坐标转换计算。不过2d顶点数比较。不像3d模型动辄上千顶点。

 反正3d模型没这么干就ok,只是记录一下。 自己计算了的话这里可以不用再次计算。 我的做法是增加

了一个 单位矩阵的判断, 毕竟矩阵乘法还是有开销的

 

 

 

 

然后找到了一个遇到同样问题的文章:

3.0 onDraw 渲染的坐标问题?

Cocos2d-x

14-07-8

我是为了实现显示一张图片,然后指定图片显示的顶点来实现显示图片的任意形状。然后继承了Sprite并重写了onDraw,代码如下。

 
 

void SpritePoly::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags){
    Sprite::draw(renderer,transform,flags);
 _customCommand.init(_globalZOrder);
 _customCommand.func = =](){
 CC_NODE_DRAW_SETUP();


        if(getTexture()!=NULL){
 GL::bindTexture2D(getTexture()->getName());
        }else{
            GL::bindTexture2D(0);
        }
 
 GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
 
        //顶点
 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertexs_);
 
        //纹理
 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, 0, uvs_);
 
        //颜色。
 glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, colors_);
 
 //根据索引draw三角形
 glDrawElements(GL_TRIANGLES, (verCont_-2)*3 , GL_UNSIGNED_SHORT, indices_);
 
    };
    renderer->addCommand(&_customCommand);
}

问题来了,我自己绘制的精灵坐标在0.0点,而系统的可以正确的位置。怎么样才能让我绘制的和系统的精灵保持同一位置? 

 

vvvsnoopy

14-07-9

顶啊:12:
求解决啊

 

vvvsnoopy

14-07-9

:12:不解决不沉贴

 

vvvsnoopy

14-07-9

:12: 求高手解决。

 

vvvsnoopy

14-07-10

:12:。。。。。。。。。。

 

vvvsnoopy

14-07-11

:12:  :12:  :12:  :12:

 

vvvsnoopy

14-07-14

:6:  :6:  :6:  :6:  :6:  :6:

 

stormliu

14-07-14

cocos2d好像不给custom command进行定点坐标系转换,咳咳,再说它也不知道你有啥定点。

你估计需要手动把顶点和串联后的transform矩阵进行乘法运算。

你的这个代码功能,跟batchnode的几乎一样,可以参考下它的代码。

 

vvvsnoopy

14-07-14

终于有人回话了。按理来说我不是设置了setPoint吗?我是继承的精灵。你说的batchNode具体指的是?

 

stormliu

14-07-14

手头没cocos代码,只能按印象说下。

好像叫SpriteBatchNode吧。

数据是继承了,但是行为没继承。sprite使用普通的command(名字忘了)。这个结构里有顶点信息Quard4和串联后的转换矩阵。

cocos在把顶点信息写入opengl buffer前,进行了一次矩阵乘法,参考类Render。custom command好像没有顶点信息,你需要自己去乘一下。

 

vvvsnoopy

14-07-14

对。精灵用的是QuadCommand,通过设置参数,然后再特定解析这个QuadCommand,进行渲染,包括矩阵信息。但是custom command没有。只有一个方法。

我看DrawNode 是通过。 director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldModelView);
去实现的。如果注释的话draw的绘制也是在0.0坐标。
问题是,我写了这句话没有用。我不知道为什么?这个问题我卡几个月了。从3.0出来一直存在。求帮忙解决。

 

stormliu

14-07-14

pushMatrix和loadMatrix好像废弃不建议使用了。它修改的是cocos2d的矩阵堆栈,跟opengl无关。

你的custom command直接操作opengl,已经把cocos2d的所有的后续处理都旁路了,调用cocos的函数肯定是不会起作用的。

Node的visit函数里有个if (xxxdirty) { transform(xxoo); }返回的就是串联后的矩阵,cocos叫它模型矩阵。

render里有个转换函数,名字忘了。你看看它是怎么把模型矩阵和原始顶点坐标转换成opengl坐标的。应该能直接调用这个函数,spritebatchnode里好像用的也是这个函数。

 

vvvsnoopy

14-07-14

看了下,还是不太懂这个流程啊。。。。 :12: 
以前2.x是好的。不需要设置什么的。坐标是走的sprite的setpoint。
这个问题应该就是简单的设置几个API吧。求大牛帮忙看看。感谢不尽,说下具体调用什么能实现坐标改变。我也不懂openGL。

 

stormliu

14-07-14

2.x的代码我没看过,我是从3.0开始接触cocos2d的。估计2.x的代码修改了opengl的模型矩阵状态,否则不可能生效的。

你可以把你要填充的顶点都转换一下。sprite的draw函数传进来的那个Mat4,应该就是model的仿射矩阵,Mat4好像有个函数叫transformPoint。把模型坐标转换成opengl坐标,再填充到你的VB里。

再不干脆改变一下opengl的模型矩阵吧。把那个mat4,压入opengl,不过记得渲染后要改回来,否则后面的渲染就全乱套了。custom command不被优化,
每个custom command对于cocos来说都是一次call。所以修改opengl状态反倒是划算的,如果你的顶点数量比较多的话,省得乘来乘去的,让显卡去乘吧。

 

vvvsnoopy

14-07-14

非常感谢。我可以手转了。只需要改顶点。。。我太笨了,以为改不了。现在可以了。谢谢了。
//顶点
glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertexs_);
直接改vertexs_:14:

 

1月后

yinyibo4610059

14-08-30

可以问一下 怎么指定顶点的吗?? 我游戏里有个需求也是这样的 要显示图片的任意形状部分,不过opgl 不太会写,可以指点以下吗?

 

你好!heart_eyes 看起来你挺喜欢这个讨论,但是你还没有注册账户。

当你创建了账户,我们能准确地追踪你的阅读进度,所以你能够在下一次访问时回到你上次阅读到的地方。你也可以在有新帖子的时候收到网页和邮件通知。并且你可以赞任何帖子来分享你的感谢。heartbeat

 注册 明天提醒我不了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值