Introduction
Custom drawing can be done in cocos2dx by deriving from Node class and using the shaders available in cocos2dx or by creating shader by our self.
Create a base class for Mesh
Lets create a class which will act as a base for mesh. You would be deriving from this class and providing required information to get the mesh drawn.
Class skeleton is show below,
class CustomShape { public: virtual ~CustomShape(); virtual void init() = 0; virtual float * vertices() = 0; virtual float * texCoords() = 0; virtual float * colors() = 0; virtual int primitive() = 0; virtual int verticesCount() = 0; virtual int coordSize() = 0; };
Create a Node class implementation
Create a class called TexturedMeshNode which is deriving from Node class.
Class sekeleton is show below,
class TexturedMeshNode: public Node { public: bool init(); void setShape(CustomShape *shape) { mShape = shape; } void draw(Renderer *renderer, const Mat4& transform, uint32_t flags); void onDraw(const Mat4 &transform, uint32_t flags); void setTexture(Texture2D *texture) { mTexture = texture; } CREATE_FUNC(TexturedMeshNode); private: CustomShape *mShape; Texture2D * mTexture; CustomCommand mCustomCommand; };
Method implementation
init
In the init method will set the shader for the class.
bool TexturedMeshNode::init() { setGLProgram(ShaderCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_TEXTURE)); }
draw
void TexturedMeshNode::draw(Renderer *renderer, const Mat4& transform, uint32_t flags) { if (mShape) { mCustomCommand.init(_globalZOrder); mCustomCommand.func = CC_CALLBACK_0(TexturedMeshNode::onDraw, this, transform, flags); renderer->addCommand(&mCustomCommand); } }
onDraw
void TexturedMeshNode::onDraw(const Mat4 &transform, uint32_t flags) { auto glProgram = getGLProgram(); glProgram->use(); glProgram->setUniformsForBuiltins(transform); if (mShape) { GL::bindTexture2D(mTexture->getName()); GL::enableVertexAttribs(GL::VERTEX_ATTRIB_FLAG_POSITION | GL::VERTEX_ATTRIB_FLAG_TEX_COORD); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, mShape->coordSize(), GL_FLOAT, GL_FALSE, 0, mShape->vertices()); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, 0, mShape->texCoords()); glDrawArrays(mShape->primitive(), 0, mShape->verticesCount()); } CC_INCREMENT_GL_DRAWS(1); }
A simple rectangle mesh implementation
Class declaration
class Rectangle : public CustomShape { private: float mX; float mY; float mWidth; float mHeight; std::vectormVertices; std::vector mTexCoords; public: Rectangle(float x, float y, float w, float h) : mX(x), mY(y), mWidth(w), mHeight(h) {} float * vertices() { return mVertices.data(); } float * texCoords() { if (mTexCoords.empty()) { return 0; } return mTexCoords.data(); } float * colors() { return 0; } int verticesCount() { return mVertices.size() / coordSize(); } int primitive(); void init(); int coordSize() { return 3; } };
Class implementation
void Rectangle::init() { mVertices.clear(); mTexCoords.clear(); float v[] = { mX, mY, 0.0f, mX+mWidth, mY, 0.0f, mX+mWidth, mY+mHeight, 0.0f, mX, mY+mHeight, 0.0f }; float t[] = { 0, 1, 1, 1, 1, 0, 0, 0 }; mVertices.insert(mVertices.begin(), v, v + sizeof(v)/sizeof(v[0])); mTexCoords.insert(mTexCoords.begin(), t, t + sizeof(t)/sizeof(t[0])); } int Rectangle::primitive() { return GL_TRIANGLE_FAN; }
Using the textured mesh class
The TexturedMeshNode can be used from other classes as shwo below,
CustomShape *shape = new Rectangle(10, 10, 100, 200); TexturedMeshNode *texturedMeshNode = TexturedMeshNode::create(); texturedMeshNode->setShape(shape); texturedMeshNode->setTexture(texture); this->addChild(texturedMeshNode);
Hi There,
ReplyDeleteBrilliant article, glad I slogged through the Custom mesh rendering with texture in cocos2d-x it seems that a whole lot of the details really come back to from my past project.
I made a basic calculator using this codes. What i want to learn is how to make a loop after the program ask "try again y/n"? it will return to choose an operation.
Code:
#include
#include
int main(){
int num1, num2, choice;
printf("Choose an operation\n\n");
printf("[1] Add\n[2] Subtract\n[3] Multiply\n[4] Divide\n[5] Exit\n");
scanf("%d", &choice);
switch(choice){
case 1:
printf("Enter 1st number:\n");
scanf("%d", &num1);
printf("Enter 2nd number:\n");
scanf("%d", &num2);
printf("\n%d", (num1+num2));
break;
case 2:
printf("Enter 1st number:\n");
scanf("%d", &num1);
printf("Enter 2nd number:\n");
scanf("%d", &num2);
printf("\n%d ", (num1-num2));
break;
case 3:
printf("Enter 1st number:\n");
scanf("%d", &num1);
printf("Enter 2nd number:\n");
scanf("%d", &num2);
printf("\n%d", (num1*num2));
break;
case 4:
printf("Enter 1st number:\n");
scanf("\n%d", &num1);
printf("Enter 2nd number:\n");
scanf("%d", &num2);
printf("\n%d", (num1/num2));
break;
case 5:
return 0;
default:
printf("That is not a valid choice.");
break;
}
getch();
}
Awesome! Thanks for putting this all in one place. Very useful!
Thanks a heaps,
Preethi