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::vector mVertices;
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