target is to achieve -> a circular clipper on the profile pictures in cocos2dx, so the profile picture looks like as they look like in the whatsapp profile picture nowadays.
I want to set a clipper first on the profile picture, then scale it according to the requirement.
I've used RenderTexture for this purposes in cocos2d-x v2.x. believe this approach would also work with v3.x. here is pseudocode:
sprite* MaskedSpriteWithSprite(textureSpriteName, maskSpriteName)
{
sprite* textureSprite = create(textureSpriteName);
sprite* maskSprite = create(maskSpriteName);
textureSprite->setPosition(ccp(textureSprite.width * 0.5f, textureSprite.height * 0.5f));
maskSprite->setPosition(ccp(maskSprite.width * 0.5f, maskSprite.height * 0.5f));
renderTexture* rt = renderTexture::create(maskSprite.width, maskSprite.height);
ccBlendFunc bfMask = ccBlendFunc();
bfMask.src = GL_ONE;
bfMask.dst = GL_ZERO;
maskSprite->setBlendFunc(bfMask);
// turn off anti-aliasing around the mask sprite
maskSprite->getTexture()->setAliasTexParameters();
ccBlendFunc bfTexture = ccBlendFunc();
bfTexture.src = GL_DST_ALPHA;
bfTexture.dst = GL_ZERO;
textureSprite->setBlendFunc(bfTexture);
rt->begin();
maskSprite->visit();
textureSprite->visit();
rt->end();
// generate the resulting sprite
sprite* pOutcome = sprite::createWithTexture(rt->getSprite()->getTexture());
pOutcome->setFlipY(true);
return pOutcome;
}
Related
I have recently been working on a project that involves the PhysX library. I need to create a PxRigidDynamic actor from a triangle mesh. I saw the example that the documentation provided, but I have some issues with this method.
The issues that I had were mainly:
The object wasn't effected by gravity, and would just sit there and vibrate (Although, I have a feeling I did something else wrong)
From what I have read, to create a rigid body from a triangle mesh, the object needs to be kinematic. This then throws an error when I try to change the object's velocity.
Here is how I am currently creating the triangle mesh:
PhysX::PxTriangleMeshDesc meshDesc;
meshDesc.points.count = numVertices;
meshDesc.points.stride = sizeof(float) * 3;
meshDesc.points.data = vertices;
meshDesc.triangles.count = numIndices;
meshDesc.triangles.stride = 3 * sizeof(uint32_t);
meshDesc.triangles.data = indices;
PhysX::PxDefaultMemoryOutputStream writeBuffer;
PhysX::PxTriangleMeshCookingResult::Enum result;
bool status = cooking->cookTriangleMesh(meshDesc, writeBuffer, &result);
if (!status)
return false;
PhysX::PxDefaultMemoryInputData readBuffer(writeBuffer.getData(),
writeBuffer.getSize());
PhysX::PxTriangleMesh* triangleMesh =
physics->createTriangleMesh(readBuffer);
dynamicObject = physics->createRigidDynamic(PhysX::PxTransform(PhysX::PxVec3(0.0f)));
if (!dynamicObject)
return false;
dynamicObject->setMass(10.0f);
dynamicObject->setRigidBodyFlag(
PhysX::PxRigidBodyFlag::eKINEMATIC, true);
material = physics->createMaterial(0.5f, 0.5f, 0.6f);
if (!material)
return false;
shape = PhysX::PxRigidActorExt::createExclusiveShape(
*dynamicObject,
PhysX::PxTriangleMeshGeometry(triangleMesh,
PhysX::PxMeshScale(PhysX::PxVec3(scale.x, scale.y, scale.z))),
*material
);
if (!shape)
return false;
How can I solve these issues?
If this isn't possible, I would like to know how to convert a triangle mesh into a convex mesh.
I use Qt3D in my project, I need to change texture of the plane dynamicly. For this I use my implementation of QAbstractTextureImage.
I do:
auto planeMaterial = new Qt3DExtras::QTextureMaterial();
Qt3DRender::QTexture2D *planeTexture = new Qt3DRender::QTexture2D();
auto *planeTextureImage = new PaintedTextureImage();
planeTextureImage->update();
planeTexture->addTextureImage(planeTextureImage);
planeMaterial->setTexture(planeTexture);
Qt3DCore::QTransform *planeTransform = new Qt3DCore::QTransform();
planeTransform->setRotationX(90);
planeTransform->setTranslation(QVector3D(0.0f, 0.0f, 15.0f));
auto planeEntity = new Qt3DCore::QEntity(this->rootEntity);
planeEntity->addComponent(mPlane);
planeEntity->addComponent(planeMaterial);
planeEntity->addComponent(planeTransform);
planeEntity->setEnabled(true);
In my scenemodifier. So it adds plane to the scene with material using texture. mPlane has width and height: 4.0 and 3.0. The image for texture has resolution 640x480, so it's 4:3 too.
void PaintedTextureImage::paint(QPainter *painter)
{
...
current = QImage((uchar*)color.data, color.cols, color.rows, color.step, QImage::Format_RGB888);
painter->drawImage(0, 0, current);
}
This is how 'current' looks if I save it to file:
And this is how it looks painted as textue:
So image quality became VERY bad and I can't understand why.
Solution:
planeTextureImage->setWidth(640);
planeTextureImage->setHeight(480);
Default was 256x256.
In all tutorials I found about creating projection matrix based on viewport size all of them assumed that left bottom coordinates of viewport will be (0,0).
Now I want to draw to the different parts of the screen and for that purpose I want to switch viewports accordingly:
glViewport(0,0,windowWidth/2, windowHeight/2); //left bottom
glViewport(0,windowHeight/2,windowWidth/2, windowHeight/2);//left top
glViewport(windowWidth/2,0,windowWidth/2, windowHeight/2);//right bottom
glViewport(windowWidth/2, windowHeight/2,windowWidth/2, windowHeight/2);//right top
Now I have a problem with defining my projection matrix. Without having any (x,y) offest I was using this code for calculating my ortho projection matrix:
if (m_WindowWidth > m_WindowHeight)
{
auto viewportAspectRatio = (float)m_WindowWidth / (float)m_WindowHeight;
m_ProjectionMatrix.m_fLeft = (-1.0f) * m_fWindowSize * viewportAspectRatio;
m_ProjectionMatrix.m_fRight = m_fWindowSize * viewportAspectRatio;
m_ProjectionMatrix.m_fBottom = (-1.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fTop = m_fWindowSize;
m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;
m_fMoveSpeed = static_cast<GLfloat>(m_fWindowSize * 2 / static_cast<float>(m_WindowHeight));
}
else
{
auto viewportAspectRatio = (float)m_WindowHeight / (float)m_WindowWidth;
m_ProjectionMatrix.m_fLeft = (-1.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fRight = m_fWindowSize;
m_ProjectionMatrix.m_fBottom = (-1.0f)*m_fWindowSize * viewportAspectRatio;
m_ProjectionMatrix.m_fTop = m_fWindowSize * viewportAspectRatio;
m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;
m_fMoveSpeed = static_cast<GLfloat>(m_fWindowSize * 2 / static_cast<float>(m_WindowWidth));
}
And this works fine UNTIL I will add any (x,y) offset to my viewport. The effect is following when using glViewport(0, m_WindowHeight/2, m_WindowWidth/2, m_WindowHeight/2):
And with glViewport(0, 0, m_WindowWidth/2, m_WindowHeight/2):
How can I make it work?
First, aspect ratio is always width/height.
Then I think what you are looking for is :
m_ProjectionMatrix.m_fLeft = x;
m_ProjectionMatrix.m_fRight = x + m_WindowWidth;
m_ProjectionMatrix.m_fBottom = y;
m_ProjectionMatrix.m_fTop = y + m_WindowHeight;
m_ProjectionMatrix.m_fNear = -(10.0f)*m_fWindowSize;
m_ProjectionMatrix.m_fFar = (10.0f)*m_fWindowSize;
Have a look at this wiki page
I found solution to this problem and posted it on the gamedev forum:
https://gamedev.stackexchange.com/questions/122284/glviewport-offset-and-ortho-projection/122289#122289
In short:
I was drawing my whole scene to the framebuffer and then I rendered generated texture to the screen. This operation caused unwanted glViewport() transformations accumulation.
Solution to this is setting the glViewport() to origin befrore rendering to the framebuffer and then setting offset when rendering texture to the screen.
Me and a friend of mine are trying to make a tank with cocos2dx.
we are so far that the tank is on the screen and the barrel is attached to the tank
but now we want to try to the rotate the barrel but nothing is happening, the joint is at the center where the barrel start en de dome ends. both the tank and the barrel are dynamic bodies and we are using a friction joint (see code)
// Create sprite and add it to the layer
CCSprite *tank = CCSprite::create();
//tank->initWithFile("../Resources/tanks/001/tank.png");
tank->setPosition(pos);
tank->setTag(1);
this->addChild(tank);
// Create ball body
b2BodyDef tankBodyDef;
tankBodyDef.type = b2_dynamicBody;
tankBodyDef.position = toMeters(&pos);
tankBodyDef.userData = tank;
tankBody = _world->CreateBody(&tankBodyDef);
// Create shape definition and add body
shapeCache->addFixturesToBody(tankBody, "001/tank");
pos = CCPointMake(580, 450);
// Create sprite and add it to the layer
CCSprite *barrel = CCSprite::create();
//barrel->initWithFile("Tanks/001/barrel.png");
barrel->setPosition(pos);
barrel->setTag(2);
this->addChild(barrel);
// Create ball body
b2BodyDef barrelBodyDef;
barrelBodyDef.type = b2_dynamicBody;
barrelBodyDef.position = toMeters(&pos);
barrelBodyDef.userData = barrel;
barrelBody = _world->CreateBody(&barrelBodyDef);
tankBarrelAnchor = CreateRevoluteJoint(tankBody, barrelBody, -85.f, 180.f, 2000000.f, 0.f, true, false);
tankBarrelAnchor->localAnchorA = b2Vec2(0, 0);
tankBarrelAnchor->localAnchorB = b2Vec2(0, 0);
tankBarrelAnchor->referenceAngle = 0;
joint = (b2RevoluteJoint*)_world->CreateJoint(tankBarrelAnchor);
b2RevoluteJointDef* Level::CreateRevoluteJoint(b2Body* A, b2Body* B, float lowerAngle, float upperAngle, float maxMotorTorque, float motorSpeed, boolean enableMotor, boolean collideConnect){
b2RevoluteJointDef *revoluteJointDef = new b2RevoluteJointDef();
revoluteJointDef->bodyA = A;
revoluteJointDef->bodyB = B;
revoluteJointDef->collideConnected = collideConnect;
revoluteJointDef->lowerAngle = CC_DEGREES_TO_RADIANS(lowerAngle);
revoluteJointDef->upperAngle = CC_DEGREES_TO_RADIANS(upperAngle);
revoluteJointDef->enableLimit = true;
revoluteJointDef->enableMotor = enableMotor;
revoluteJointDef->maxMotorTorque = maxMotorTorque;
revoluteJointDef->motorSpeed = CC_DEGREES_TO_RADIANS(motorSpeed); //1 turn per second counter-clockwise
return revoluteJointDef;
}
I think the problem is that your anchor positions are not correct. This setting:
tankBarrelAnchor->localAnchorA = b2Vec2(0, 0);
tankBarrelAnchor->localAnchorB = b2Vec2(0, 0);
... would put the anchors at those two red and green axes you can see in your screenshot, and it will try to pull those two points together. Try turning on the joints display in the debug draw and this should be more obvious.
You need to give the anchors as local coordinates from the point of view of each body. For example from the point of view of the tank body, the swivel point looks like (1,2) and from the point of view of the barrel body, it looks like (-1,0). Of course the dimensions you are using are probably different, but the directions should be somewhat similar.
See the "Local anchors" section here: http://www.iforce2d.net/b2dtut/joints-revolute
As I am newbie to cocoa2d I am struggling alot to rotate the physics or dynamic body along an arc path.
The way I tried is as follows:
#define COS_ANIMATOR(position, timeCount, speed, waveMagnitude) ((cosf(timeCount * speed) * waveMagnitude) + position)
#define SIN_ANIMATOR(position, timeCount, speed, waveMagnitude) ((sinf(timeCount * speed) * waveMagnitude) + position)
CCSpriteBatchNode *pipe_parent = [CCSpriteBatchNode batchNodeWithFile:#"pipe.png" capacity:100];
CCTexture2D *pipeSpriteTexture_ = [pipe_parent texture];
PhysicsSprite *pipeSprite = [PhysicsSprite spriteWithTexture:pipeSpriteTexture_ rect:CGRectMake(0 ,0 ,55,122)];
//pipe = [CCSprite spriteWithFile:#"pipe.png"
// rect:CGRectMake(0, 0, 55, 122)];
[self addChild:pipeSprite];
// pipe.position = ccp(s.width/2 , 420.0);
b2BodyDef myBodyDef;
myBodyDef.type = b2_staticBody; //this will be a dynamic body
myBodyDef.position.Set(((s.width/2) - 90)/PTM_RATIO, 420.0/PTM_RATIO); //set the starting position
myBodyDef.angle = 0; //set the starting angle
b2Body* staticBody = world->CreateBody(&myBodyDef);
b2PolygonShape boxShape;
boxShape.SetAsBox(1,1);
b2FixtureDef boxFixtureDef;
boxFixtureDef.shape = &boxShape;
boxFixtureDef.density = 1;
boxFixtureDef.userData = pipeSprite;
boxFixtureDef.filter.groupIndex = -1;
staticBody->CreateFixture(&boxFixtureDef);
[pipeSprite setPhysicsBody:staticBody];
-(void) draw
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
[super draw];
const CGPoint newSpritePosition = ccp(COS_ANIMATOR(150, mTimeCounter, 0.05,50), SIN_ANIMATOR(400, mTimeCounter, -0.05, 50));
pipeSprite.position = newSpritePosition;
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData();
kmGLPopMatrix();
}
on following this approach my sprite rotating in circular motion instead of rotating in an arc path.
Please give your ideas or suggestions.
Thanks all
I'm not entirely sure what it is you are looking to accomplish when you talk about rotating in an arc path. I only see you setting a position, not a rotation, so are you just wanting to set a position, or a rotation, or both? Your position code looks like you are trying to achieve a circular (or elliptical) path because you are using the sine and cosine in the x,y position.
If you're looking to move a sprite along a sine curve, I did that today and it took a bit of trial and error. I had some variables for the amplitude and period, and from there I traced out a nice sine curve movement in the sprite's update: method.
CGPoint initialPosition; // set this to the sprite's initial position
float amplitude; // in points
float period; // in points
float y, x = initialPosition.x;
-(void) update:(ccTime)dt
{
x += dt * 100; // speed of movement across the screen. Picked by trial and error.
y = initalPosition.y + amplitude * sinf((x - initialPosition.x)/period);
sprite.position = ccp(x,y);
sprite.rotation = cosf((x - initialPosition.x)/period); // optional if you want to rotate along the path as well
}
Don't know if this is anything you are looking for but it might give you some ideas.