Bullet(Cocos2dx)之优化PhysicsDraw3D

Bullet(Cocos2dx)之优化PhysicsDraw3D,第1张

概述为了测试bullet物体的大小,匆匆写完的PhysicsDraw3D的效率低的要命,这也是为什么cocos2dx弃用了DrawPrimitives,而去使用DrawNode DrawPrimitives每次绘制都去调用glDrawElements,假如每帧绘制10000条线段,那么就要调用10000次glDrawElements,可见效率之低。 而DrawNode采取的是批处理的方式,当drawL

为了测试bullet物体的大小,匆匆写完的PhysicsDraw3D的效率低的要命,这也是为什么cocos2dx弃用了DrawPrimitives,而去使用DrawNode

DrawPrimitives每次绘制都去调用glDrawElements,假如每帧绘制10000条线段,那么就要调用10000次glDrawElements,可见效率之低。

而DrawNode采取的是批处理的方式,当drawline的时候不是立即绘制,而是将线段的信息添加到数组里,当draw时统一调用gl的绘制函数

10000/1可不是一个小数目啊。

下图使用DrawPrimitives方法


加入40Sphere帧率就掉到4070的帧率更是惨不忍睹


下图使用DrawNode方法


为了解决这个问题就要参照DrawNode实现一个简单的DrawNode3D

不管三七二十一,将DrawNode的头文件代码copy,删去一些不需要的,

1.修改V2F_C4B_T2F3F_C4B_T2F

2.修改Vec2为Vec3,要绘制3D

3.保留drawPoint,drawPoints,drawline,其他的绘制函数不要

#ifndef __DRAW_NODE_3D_H__#define __DRAW_NODE_3D_H__#include "cocos2d.h"USING_NS_CC;class DrawNode3D : public Node{public:	static DrawNode3D* create();	voID drawPoint(const Vec3& point,const float pointSize,const color4F &color);	voID drawPoints(const Vec3 *position,unsigned int numberOfPoints,const color4F &color);	voID drawline(const Vec3 &origin,const Vec3 &destination,const color4F &color);	// OverrIDes	virtual voID draw(Renderer *renderer,const Mat4 &transform,uint32_t flags) overrIDe;    voID clear();    const BlendFunc& getBlendFunc() const;    voID setBlendFunc(const BlendFunc &blendFunc);    voID onDraw(const Mat4 &transform,uint32_t flags);    voID onDrawGLline(const Mat4 &transform,uint32_t flags);    voID onDrawGLPoint(const Mat4 &transform,uint32_t flags);CC_CONSTRUCTOR_ACCESS:	DrawNode3D();	virtual ~DrawNode3D();	virtual bool init();protected:	voID ensureCapacity(int count);	voID ensureCapacityGLPoint(int count);	voID ensureCapacityGLline(int count);	gluint      _vao;	gluint      _vbo;	gluint      _vaoGLPoint;	gluint      _vboGLPoint;	gluint      _vaoGLline;	gluint      _vboGLline;	int         _bufferCapacity;	GLsizei     _bufferCount;	V3F_C4B_T2F *_buffer;	int         _bufferCapacityGLPoint;	GLsizei     _bufferCountGLPoint;	V3F_C4B_T2F *_bufferGLPoint;	color4F     _pointcolor;	int         _pointSize;	int         _bufferCapacityGLline;	GLsizei     _bufferCountGLline;	V3F_C4B_T2F *_bufferGLline;	BlendFunc   _blendFunc;	CustomCommand _customCommand;	CustomCommand _customCommandGLPoint;	CustomCommand _customCommandGLline;	bool        _dirty;	bool        _dirtyGLPoint;	bool        _dirtyGLline;private:	CC_disALLOW_copY_AND_ASSIGN(DrawNode3D);};#endif

对于DrawNode.cpp按照上面所说同样修改

要记住

glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_position,3,GL_float,GL_FALSE,sizeof(V3F_C4B_T2F),(GLvoID *)offsetof(V3F_C4B_T2F,vertices));要将GLProgram::VERTEX_ATTRIB_position,2 改为 GLProgram::VERTEX_ATTRIB_position,3

因为顶点有三个元素,.cpp代码过多,请在文章最后下载源码,要注意的是绘制时开启深度测试

修改PhysicsDraw3D

删除成员变量,添加DrawNode3D*_drawNode,由于DrawNode3D继承自Node所以创建时要将其添加到父节点上,

修改create,init为如下

staticPhysicsDraw3D*createWithLayer(Node*layer);

boolinitWithLayer(Node*layer);

同时添加

voIDclearDraw();

我们知道DrawNode如果不执行clear,那么就不会清空上一帧的绘制数据

具体修改如下:

PhysicsDraw3D* PhysicsDraw3D::createWithLayer(Node* layer){	auto draw = new PhysicsDraw3D;	if (draw && draw->initWithLayer(layer))	{		return draw;	}	return nullptr;}bool PhysicsDraw3D::initWithLayer(Node* layer){		_drawNode = DrawNode3D::create();	layer->addChild(_drawNode);	_deBUGDrawMode = btIDeBUGDraw::DBG_MAX_DEBUG_DRAW_MODE;	return true;}voID PhysicsDraw3D::clearDraw(){	_drawNode->clear();}

销毁时也要将_drawNode从Parent中移除

voID PhysicsDraw3D::destroy(){	_drawNode->removeFromParent();	delete this;}drawline也就简化了voID PhysicsDraw3D::drawline(const btVector3& from,const btVector3& to,const btVector3& color){	Vec3 vertices[2] = {		Vec3(from.x(),from.y(),from.z()),Vec3(to.x(),to.y(),to.z())	};	_color.r = color.x();	_color.g = color.y();	_color.b = color.z();	_color.a = 1.f;	_drawNode->drawline(vertices[0],vertices[1],_color);}

PhysicsWorld3D创建的静态函数添加

static PhysicsWorld3D* createWithDeBUG(Node* layer,const btVector3& gravity = btVector3(0,-10,0));

为的就是创建调试绘制

bool PhysicsWorld3D::initWorlDWithDeBUG(Node* layer,const btVector3& gravity){	if (!this->initWorld(gravity))	{		return false;	}	_deBUGDraw = PhysicsDraw3D::createWithLayer(layer);	_world->setDeBUGDrawer(_deBUGDraw);		return true;}

同时删除initWorld对_deBUGDraw的创建,每次绘制时需要判断是否为deBUG

voID PhysicsWorld3D::deBUGDraw(){	if (_deBUGDraw)	{		_deBUGDraw->clearDraw();		_world->deBUGDrawWorld();	}}

完整源码

csdn

github

总结

以上是内存溢出为你收集整理的Bullet(Cocos2dx)之优化PhysicsDraw3D全部内容,希望文章能够帮你解决Bullet(Cocos2dx)之优化PhysicsDraw3D所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/1029814.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-23
下一篇2022-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存