How can I draw something on the sprite not behind sprite - cocos2d-x

I use cocos2dx v3.8, and successful draw things with override draw like:
void Box2dManager::draw(Renderer *renderer, const Mat4& transform, uint32_t flags){
GL::enableVertexAttribs( GL::VERTEX_ATTRIB_FLAG_POSITION );
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
box2dWorld->DrawDebugData();
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
// super::draw(renderer, transform, flags);
}
but It always behind the sprites. It can't change after modify z-order.
SOLVED
Now I can fix cocos2d v3.x box2d DrawDebugData problem.
And I paste all the cocos2dx solve code.
v2: (simple, because v2 engine opengl draw is each single task)
void Box2dManager::draw(){
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
box2dWorld->DrawDebugData();
kmGLPopMatrix();
}
v3: (v3 engine push the draw commond to core with quence, so you need create a callback )
void Box2dManager::draw(Renderer *renderer, const Mat4& transform, uint32_t flags){
super::draw(renderer, transform, _transformUpdated);
GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_modelViewMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Box2dManager::onDraw, this);
renderer->addCommand(&_customCommand);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void Box2dManager::onDraw() {
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
Mat4 oldMV;
oldMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewMV);
box2dWorld->DrawDebugData();
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldMV);
}
refrence:
http://discuss.cocos2d-x.org/t/box2d-debug-drawing-for-cocos2d-x-3-0/11912/2
http://blog.csdn.net/zszeng/article/details/50000757

Now I can fix cocos2d v3.x box2d DrawDebugData problem.
And I paste all the cocos2dx solve code.
v2: (simple, because v2 engine opengl draw is each single task)
void Box2dManager::draw(){
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
box2dWorld->DrawDebugData();
kmGLPopMatrix();
}
v3: (v3 engine push the draw commond to core with quence, so you need create a callback )
void Box2dManager::draw(Renderer *renderer, const Mat4& transform, uint32_t flags){
super::draw(renderer, transform, _transformUpdated);
GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_modelViewMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(Box2dManager::onDraw, this);
renderer->addCommand(&_customCommand);
director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
void Box2dManager::onDraw() {
Director* director = Director::getInstance();
CCASSERT(nullptr != director, "Director is null when seting matrix stack");
Mat4 oldMV;
oldMV = director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewMV);
box2dWorld->DrawDebugData();
director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, oldMV);
}
refrence:
http://discuss.cocos2d-x.org/t/box2d-debug-drawing-for-cocos2d-x-3-0/11912/2
http://blog.csdn.net/zszeng/article/details/50000757

How about you use a DrawNode and add it as a child? It would be easier to maintain if you were to use a node that you manage on the drawing tree.
auto myDrawing = DrawNode::create();
myDrawing::drawRect(p1, p2, p3, Color4F(255, 255, 0, 255));
myDrawing::setLineWidth(2)
this->addChild(myDrawing);

virtual void draw (cocos2d::Renderer* renderer, const cocos2d::Mat4& transform,uint32_t flags) override;
cocos2d::CustomCommand _customCmd;
void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);
void linedraw:: draw(cocos2d::Renderer* renderer, const cocos2d::Mat4 &transform, uint32_t flags){
//cocos2d::Layer::draw(renderer, transform, flags);
_customCmd.init(1);
_customCmd.func = CC_CALLBACK_0(linedraw::onDraw, this, transform, flags);
renderer->addCommand(&_customCmd);
}
void linedraw:: onDraw(const cocos2d::Mat4 &transform, uint32_t flags)
{
}

Related

Libgdx crop image to circle

I'm looking for a way to crop a photo taken from the users gallery to a circle, to be displayed as a profile picture basically.
I've been recommended to use Masking .
But I can't work out how to actually do it. There are virtually no examples of it, except with android code. But since I'm going to port my game to IOS as well I need a Libgdx solution.
So has anyone done this before and have an working example perhaps?
Here's how I'll fetch the image:
ublic void invokeGallery() {
if (utils != null) {
loading = true;
utils.pickImage(new utilsInterface.Callback() {
#Override
public ImageHandler onImagePicked(final InputStream stream) {
loading = true;
final byte[] data;
try {
data = StreamUtils.copyStreamToByteArray(stream);
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
loading = false;
}
});
} catch (IOException e) {
e.printStackTrace();
}
loading = false;
return null;
}
});
}
}
I use this, it works, but there is no interpolation, which means the edges are pixelated. You can chose to either implement interpolation or use a border!
public static Pixmap roundPixmap(Pixmap pixmap)
{
int width = pixmap.getWidth();
int height = pixmap.getHeight();
Pixmap round = new Pixmap(pixmap.getWidth(),pixmap.getHeight(),Pixmap.Format.RGBA8888);
if(width != height)
{
Gdx.app.log("error", "Cannot create round image if width != height");
round.dispose();
return pixmap;
}
double radius = width/2.0;
for(int y=0;y<height;y++)
{
for(int x=0;x<width;x++)
{
//check if pixel is outside circle. Set pixel to transparant;
double dist_x = (radius - x);
double dist_y = radius - y;
double dist = Math.sqrt((dist_x*dist_x) + (dist_y*dist_y));
if(dist < radius)
{
round.drawPixel(x, y,pixmap.getPixel(x, y));
}
else
round.drawPixel(x, y, 0);
}
}
Gdx.app.log("info", "pixmal rounded!");
return round;
}
Do keep in mind this will all be unmanaged! To make life easier I usually save the image and load it as a managed texture.

How to use fragment shader with cocos2d-x 3.1?

The code below is from this tutorial: http://www.raywenderlich.com/10862/how-to-create-cool-effects-with-custom-shaders-in-opengl-es-2-0-and-cocos2d-2-x
It is a very cool tutorial, but I don't know how to do that in cocos2d-x 3. I have translated the code below
- (id)init
{
self = [super init];
if (self) {
// 1
sprite = [CCSprite spriteWithFile:#"Default.png"];
sprite.anchorPoint = CGPointZero;
sprite.rotation = 90;
sprite.position = ccp(0, 320);
[self addChild:sprite];
// 2
const GLchar * fragmentSource = (GLchar*) [[NSString stringWithContentsOfFile:[CCFileUtils fullPathFromRelativePath:#"CSEColorRamp.fsh"] encoding:NSUTF8StringEncoding error:nil] UTF8String];
sprite.shaderProgram = [[CCGLProgram alloc] initWithVertexShaderByteArray:ccPositionTextureA8Color_vert
fragmentShaderByteArray:fragmentSource];
[sprite.shaderProgram addAttribute:kCCAttributeNamePosition index:kCCVertexAttrib_Position];
[sprite.shaderProgram addAttribute:kCCAttributeNameTexCoord index:kCCVertexAttrib_TexCoords];
[sprite.shaderProgram link];
[sprite.shaderProgram updateUniforms];
// 3
colorRampUniformLocation = glGetUniformLocation(sprite.shaderProgram->program_, "u_colorRampTexture");
glUniform1i(colorRampUniformLocation, 1);
// 4
colorRampTexture = [[CCTextureCache sharedTextureCache] addImage:#"colorRamp.png"];
[colorRampTexture setAliasTexParameters];
// 5
[sprite.shaderProgram use];
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, [colorRampTexture name]);
glActiveTexture(GL_TEXTURE0);
}
return self;
}
and obtained this:
Vec2 origin = Director::getInstance()->getVisibleOrigin();
sprite = Sprite::create("HelloWorld.png");
sprite->setAnchorPoint(Vec2(0, 0));
sprite->setRotation(3);
sprite->setPosition(origin);
addChild(sprite);
const GLchar * fragmentSource = FileUtils::getInstance()->getStringFromFile("CSEColorRamp.fsh").c_str();
GLProgram* p = GLProgram::createWithByteArrays(ccPositionTextureA8Color_vert, fragmentSource);
sprite->setGLProgram(p);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION);
p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORD);
p->link();
p->updateUniforms();
// 3
colorRampUniformLocation = glGetUniformLocation(sprite->getGLProgram()->getProgram(), "u_colorRampTexture");
glUniform1i(colorRampUniformLocation, 1);
// 4
colorRampTexture = Director::getInstance()->getTextureCache()->addImage("colorRamp.png");
colorRampTexture->setAliasTexParameters();
// 5
sprite->getGLProgram()->use();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, colorRampTexture->getName());
glActiveTexture(GL_TEXTURE0);
But it does not work. It shows a black screen with 2 draw calls. What is wrong? Did I pass all uniforms and attributes normally to the fragment shader. Did I initialize the program correctly?
Here is an example how shader should be used in cocos2d-x 3.1:
.h file
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
using namespace cocos2d;
class HelloWorld : public cocos2d::Layer
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
virtual void visit(Renderer *renderer, const Mat4 &transform, bool transformUpdated) override;
//we call our actual opengl commands here
void onDraw();
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
private:
CustomCommand _customCommand;
GLuint vao;
GLuint vertexVBO;
GLuint colorVBO;
};
#endif // __HELLOWORLD_SCENE_H__
.cpp file
#include "HelloWorldScene.h"
USING_NS_CC;
Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//create my own program
auto program = new GLProgram;
program->initWithFilenames("myVertextShader.vert", "myFragmentShader.frag");
program->link();
//set uniform locations
program->updateUniforms();
// this->setGLProgram(GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_NAME_POSITION_COLOR));
this->setGLProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
typedef struct {
float Position[2];
float Color[4];
} Vertex;
// auto size = Director::getInstance()->getVisibleSize();
Vertex data[] =
{
{{-1,-1},{0,1,0,1}},
{{1,-1},{1,0,0,1}},
{ {-1,1},{0,0,1,1}},
{{1,1},{0,1,0,1}}
};
GLubyte indices[] = { 0,1,2, //第一个三角形索引
2,3,1}; //第二个三角形索引
glGenBuffers(1, &vertexVBO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLuint positionLocation = glGetAttribLocation(program->getProgram(), "a_position");
// CCLOG("position =%d", positionLocation);
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation,
2,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid*)offsetof(Vertex,Position));
//set for color
// glGenBuffers(1, &colorVBO);
// glBindBuffer(GL_ARRAY_BUFFER, colorVBO);
// glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLuint colorLocation = glGetAttribLocation(program->getProgram(), "a_color");
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation,
4,
GL_FLOAT,
GL_FALSE,
sizeof(Vertex),
(GLvoid*)offsetof(Vertex,Color));
GLuint indexVBO;
glGenBuffers(1, &indexVBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices) , indices, GL_STATIC_DRAW);
program->autorelease();
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// 使用vao http://blog.sina.com.cn/s/blog_4a657c5a01016f8s.html
return true;
}
void HelloWorld::visit(cocos2d::Renderer *renderer, const Mat4 &transform, bool transformUpdated)
{
Layer::draw(renderer, transform, transformUpdated);
//send custom command to tell the renderer to call opengl commands
_customCommand.init(_globalZOrder);
_customCommand.func = CC_CALLBACK_0(HelloWorld::onDraw, this);
renderer->addCommand(&_customCommand);
}
void HelloWorld::onDraw()
{
//question1: why the triangle goes to the up side
//如果使用对等矩阵,则三角形绘制会在最前面
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
auto glProgram = getGLProgram();
glProgram->use();
//set uniform values, the order of the line is very important
glProgram->setUniformsForBuiltins();
auto size = Director::getInstance()->getWinSize();
//use vao
glBindVertexArray(vao);
GLuint uColorLocation = glGetUniformLocation(glProgram->getProgram(), "u_color");
float uColor[] = {1.0, 0.0, 0.0, 1.0};
glUniform4fv(uColorLocation,1, uColor);
// glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE,(GLvoid*)0);
glBindVertexArray(0);
CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 6);
CHECK_GL_ERROR_DEBUG();
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
}
myVertextShader.vert vertex shader
attribute vec4 a_position;
attribute vec4 a_color;
varying vec4 v_fragmentColor;
uniform vec4 u_color;
void main()
{
gl_Position = CC_MVPMatrix * a_position;
v_fragmentColor = a_color * u_color;
}
myFragmentShader.frag fragment shader
varying vec4 v_fragmentColor;
void main()
{
gl_FragColor = v_fragmentColor;
}
I have used this source: http://4gamers.cn/blog/categories/opengl-es/

Box2d body generation dynamically in cocos2dx using c++ in Xcode

I am a new developer in cocos2dx.I am developing a game in which i am using the box2d bodies that are loading through physics editor.There are more than 20 bodies using in a level of the game,that i am making separate body for separate sprite attached with them and the similar bodies are used in the other levels and there are 50 levels in the game and for each level,i have made separate class and again making the b2body loading function,all the code is working properly but I just want to make a generic function for loading the bodies in a class so that i can use the same b2body loading function in all the levels.Also i have to destroy the particular body and the sprite on touching the sprite
//Sprites:
rect_sprite1=CCSprite::create("rect1.png");
rect_sprite1->setScaleX(rX);
rect_sprite1->setScaleY(rY);
this->addChild(rect_sprite1,1);
rect_sprite2=CCSprite::create("rect2.png");
rect_sprite2->setScaleX(rX);
rect_sprite2->setScaleY(rY);
this->addChild(rect_sprite2,1);
rect_sprite3=CCSprite::create("circle.png");
rect_sprite3->setScale(rZ);
this->addChild(rect_sprite3,1);
GB2ShapeCache::sharedGB2ShapeCache()->addShapesWithFile("obs.plist");
//body loading function
void Level1::addNewSpriteWithCoords()
{
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
b2BodyDef bodyDef1;
bodyDef1.type=b2_dynamicBody;
bodyDef1.position.Set((winSize.width*0.38)/PTM_RATIO,(winSize.height*0.4) /PTM_RATIO);
bodyDef1.userData = rect_sprite1;
body1 = (MyPhysicsBody*)world->CreateBody(&bodyDef1);
body1->setTypeFlag(7);
// add the fixture definitions to the body
GB2ShapeCache *sc1 = GB2ShapeCache::sharedGB2ShapeCache();
sc1->addFixturesToBody(body1,"rect1", rect_sprite1);
rect_sprite1->setAnchorPoint(sc1->anchorPointForShape("rect1"));
b2BodyDef bodyDef2;
bodyDef2.type=b2_dynamicBody;
bodyDef2.position.Set((winSize.width*0.62)/PTM_RATIO,
(winSize.height*0.4)/PTM_RATIO);
bodyDef2.userData = rect_sprite2;
body2 = (MyPhysicsBody*)world->CreateBody(&bodyDef2);
body2->setTypeFlag(7);
// add the fixture definitions to the body
GB2ShapeCache *sc2 = GB2ShapeCache::sharedGB2ShapeCache();
sc2->addFixturesToBody(body2,"rect2", rect_sprite2);
rect_sprite2->setAnchorPoint(sc2->anchorPointForShape("rect2"));
b2BodyDef bodyDef3;
bodyDef3.type=b2_dynamicBody;
bodyDef3.position.Set((winSize.width*0.5)/PTM_RATIO, (winSize.height*0.23)/PTM_RATIO);
bodyDef3.userData = rect_sprite3;
body3 = (MyPhysicsBody*)world->CreateBody(&bodyDef3);
body3->setTypeFlag(7);
// add the fixture definitions to the body
GB2ShapeCache *sc3 = GB2ShapeCache::sharedGB2ShapeCache();
sc3->addFixturesToBody(body3,"circle", rect_sprite3);
rect_sprite3->setAnchorPoint(sc3->anchorPointForShape("circle"));
}
void Level1::ccTouchesBegan(cocos2d::CCSet* touches, cocos2d::CCEvent* event)
{
if(box->containsPoint(touchPoint))
{
this->removeChild(((CCSprite*)rect),true);
if(((CCSprite*)rect)==rect_sprite1)
{
rect_sprite1=NULL;
world->DestroyBody(body1);
Utils::setCount(Utils::getCount()-1);
}
if(((CCSprite*)rect)==rect_sprite2)
{
rect_sprite2=NULL;
world->DestroyBody(body2);
Utils::setCount(Utils::getCount()-1);
}
if(((CCSprite*)rect)==rect_sprite3)
{
rect_sprite3=NULL;
world->DestroyBody(body3);
Utils::setCount(Utils::getCount()-1);
}
}
Similarly i am doing for other levels.
If anyone know about it,please suggest.Thanks
This seems more like a "What design pattern should I use?" than a specific problem with loading the code.
In general, when I want to create "Entities" that require a physical body, I use a base class that contains the Box2D body as one of its members. The base class is a container for the body (which is assigned to it) and is responsible for destroying the body (removing it from the Box2D world) when the Entity is destroyed.
Derived classes can load the body from the Box2D shape cache. This is best shown through an example. There is a game I am working on where I have a swarm of different shaped asteroids circling a sun. Here is a screen shot:
The base class, Entity, contains the body and destroys it when the Entity is destroyed:
class Entity : public HasFlags
{
public:
enum
{
DEFAULT_ENTITY_ID = -1,
};
private:
uint32 _ID;
// Every entity has one "main" body which it
// controls in some way. Or not.
b2Body* _body;
// Every entity has a scale size from 1 to 100.
// This maps on to the meters size of 0.1 to 10
// in the physics engine.
uint32 _scale;
protected:
void SetScale(uint32 value)
{
assert(value >= 1);
assert(value <= 100);
_scale = value;
}
public:
void SetBody(b2Body* body)
{
assert(_body == NULL);
if(_body != NULL)
{
CCLOG("BODY SHOULD BE NULL BEFORE ASSIGNING");
_body->GetWorld()->DestroyBody(_body);
_body = NULL;
}
_body = body;
if(body != NULL)
{
_body->SetUserData(this);
for (b2Fixture* f = _body->GetFixtureList(); f; f = f->GetNext())
{
f->SetUserData(this);
}
}
}
inline void SetID(uint32 ID)
{
_ID = ID;
}
inline uint32 GetID() const
{
return _ID;
}
virtual string ToString(bool updateDescription = false)
{
string descr = "ID: ";
descr += _ID;
descr += "Flags: ";
if(IsFlagSet(HF_IS_GRAPH_SENSOR))
descr += "IS_FLAG_SENSOR ";
return descr;
}
Entity() :
_ID(DEFAULT_ENTITY_ID),
_body(NULL),
_scale(1)
{
}
Entity(uint32 flags, uint32 scale) :
HasFlags(flags),
_ID(DEFAULT_ENTITY_ID),
_body(NULL),
_scale(scale)
{
}
virtual void Update()
{
}
virtual void UpdateDisplay()
{
}
virtual ~Entity()
{
if(_body != NULL)
{
_body->GetWorld()->DestroyBody(_body);
}
}
inline static float32 ScaleToMeters(uint32 scale)
{
return 0.1*scale;
}
inline Body* GetBody()
{
return _body;
}
inline const Body* GetBody() const
{
return _body;
}
inline uint32 GetScale()
{
return _scale;
}
inline float32 GetSizeMeters()
{
return ScaleToMeters(_scale);
}
};
The Asteroid class itself is responsible for loading one of several different "Asteroid" shapes from the shape cache. However, ALL the asteroids have common logic for making them move about the center of the screen. They have a rope joint attached and the Update(...) function adds some "spin" to them so they rotate around the center:
class Asteroid : public Entity
{
private:
b2Fixture* _hull;
Vec2 _anchor;
CCSprite* _sprite;
float32 _targetRadius;
public:
// Some getters to help us out.
b2Fixture& GetHullFixture() const { return *_hull; }
float32 GetTargetRadius() { return _targetRadius; }
CCSprite* GetSprite() { return _sprite; }
void UpdateDisplay()
{
// Update the sprite position and orientation.
CCPoint pixel = Viewport::Instance().Convert(GetBody()->GetPosition());
_sprite->setPosition(pixel);
_sprite->setRotation(-CC_RADIANS_TO_DEGREES(GetBody()->GetAngle()));
}
virtual void Update()
{
Body* body = GetBody();
Vec2 vRadius = body->GetPosition();
Vec2 vTangent = vRadius.Skew();
vTangent.Normalize();
vRadius.Normalize();
// If it is not moving...give it some spin.
if(fabs(vTangent.Dot(body->GetLinearVelocity())) < 1)
{
body->SetLinearDamping(0.001);
body->ApplyForceToCenter(body->GetMass()*1.5*vTangent);
body->ApplyForce(vRadius,body->GetMass()*0.05*vRadius);
}
else
{
body->SetLinearDamping(0.05);
}
}
~Asteroid()
{
}
Asteroid() :
Entity(HF_CAN_MOVE | HF_UPDATE_PRIO_5,50)
{
}
bool Create(b2World& world, const string& shapeName,const Vec2& position, float32 targetRadius)
{
_targetRadius = targetRadius;
_anchor = position;
string str = shapeName;
str += ".png";
_sprite = CCSprite::createWithSpriteFrameName(str.c_str());
_sprite->setTag((int)this);
_sprite->setAnchorPoint(ccp(0.5,0.5));
// _sprite->setVisible(false);
b2BodyDef bodyDef;
bodyDef.position = position;
bodyDef.type = b2_dynamicBody;
Body* body = world.CreateBody(&bodyDef);
assert(body != NULL);
// Add the polygons to the body.
Box2DShapeCache::instance().addFixturesToBody(body, shapeName, GetSizeMeters());
SetBody(body);
return true;
}
};
The Create(...) function for the Asteroid is called from the loading code in the scene, which could easily be a .csv file with the shape names in it. It actually reuses the names several times (there are only about 10 asteroid shapes).
You will notice that the Asteroid also has a CCSprite associated with it. Not all Entities have a sprite, but some do. I could have created an Entity-Derived class (EntityWithSprite) for this case so that the sprite could be managed as well, but I try to avoid too many nested classes. I could have put it into the base class, and may still. Regardless, the Asteroids contain their own sprites and load them from the SpriteCache. They are updated in a different part of the code (not relevant here, but I will be happy to answer questions about it if you are curious).
NOTE: This is part of a larger code base and there are features like zooming, cameras, graph/path finding, and lots of other goodies in the code base. Feel free to use what you find useful.
You can find all the (iOS) code for this on github and there are videos and tutorials posted on my site here.

JCuda. Reusing already used pointer

I have a trouble working with JCUDA. I have a task to make 1D FFT using CUFFT library, but the result should be multiply on 2. So I decided to make 1D FFT with type CUFFT_R2C. Class responsible for this going next:
public class FFTTransformer {
private Pointer inputDataPointer;
private Pointer outputDataPointer;
private int fftType;
private float[] inputData;
private float[] outputData;
private int batchSize = 1;
public FFTTransformer (int type, float[] inputData) {
this.fftType = type;
this.inputData = inputData;
inputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(inputDataPointer, inputData.length * Sizeof.FLOAT);
JCuda.cudaMemcpy(inputDataPointer, Pointer.to(inputData),
inputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyHostToDevice);
outputDataPointer = new CUdeviceptr();
JCuda.cudaMalloc(outputDataPointer, (inputData.length + 2) * Sizeof.FLOAT);
}
public Pointer getInputDataPointer() {
return inputDataPointer;
}
public Pointer getOutputDataPointer() {
return outputDataPointer;
}
public int getFftType() {
return fftType;
}
public void setFftType(int fftType) {
this.fftType = fftType;
}
public float[] getInputData() {
return inputData;
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
public float[] getOutputData() {
return outputData;
}
private void R2CTransform() {
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_R2C, batchSize);
JCufft.cufftExecR2C(plan, inputDataPointer, outputDataPointer);
JCufft.cufftDestroy(plan);
}
private void C2CTransform(){
cufftHandle plan = new cufftHandle();
JCufft.cufftPlan1d(plan, inputData.length, cufftType.CUFFT_C2C, batchSize);
JCufft.cufftExecC2C(plan, inputDataPointer, outputDataPointer, fftType);
JCufft.cufftDestroy(plan);
}
public void transform(){
if (fftType == JCufft.CUFFT_FORWARD) {
R2CTransform();
} else {
C2CTransform();
}
}
public float[] getFFTResult() {
outputData = new float[inputData.length + 2];
JCuda.cudaMemcpy(Pointer.to(outputData), outputDataPointer,
outputData.length * Sizeof.FLOAT, cudaMemcpyKind.cudaMemcpyDeviceToHost);
return outputData;
}
public void releaseGPUResources(){
JCuda.cudaFree(inputDataPointer);
JCuda.cudaFree(outputDataPointer);
}
public static void main(String... args) {
float[] inputData = new float[65536];
for(int i = 0; i < inputData.length; i++) {
inputData[i] = (float) Math.sin(i);
}
FFTTransformer transformer = new FFTTransformer(JCufft.CUFFT_FORWARD, inputData);
transformer.transform();
float[] result = transformer.getFFTResult();
HilbertSpectrumTicksKernelInvoker.multiplyOn2(transformer.getOutputDataPointer(), inputData.length+2);
transformer.releaseGPUResources();
}
}
Method which responsible for multiplying uses cuda kernel function.
Java method code:
public static void multiplyOn2(Pointer inputDataPointer, int dataSize){
// Enable exceptions and omit all subsequent error checks
JCudaDriver.setExceptionsEnabled(true);
// Create the PTX file by calling the NVCC
String ptxFileName = null;
try {
ptxFileName = FileService.preparePtxFile("resources\\HilbertSpectrumTicksKernel.cu");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Initialize the driver and create a context for the first device.
cuInit(0);
CUdevice device = new CUdevice();
cuDeviceGet(device, 0);
CUcontext context = new CUcontext();
cuCtxCreate(context, 0, device);
// Load the ptx file.
CUmodule module = new CUmodule();
cuModuleLoad(module, ptxFileName);
// Obtain a function pointer to the "add" function.
CUfunction function = new CUfunction();
cuModuleGetFunction(function, module, "calcSpectrumSamples");
// Set up the kernel parameters: A pointer to an array
// of pointers which point to the actual values.
int N = (dataSize + 1) / 2 + 1;
int pair = (dataSize + 1) % 2 > 0 ? 1 : -1;
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
Pointer.to(new int[] { dataSize }),
Pointer.to(new int[] { N }), Pointer.to(new int[] { pair }));
// Call the kernel function.
int blockSizeX = 128;
int gridSizeX = (int) Math.ceil((double) dataSize / blockSizeX);
cuLaunchKernel(function, gridSizeX, 1, 1, // Grid dimension
blockSizeX, 1, 1, // Block dimension
0, null, // Shared memory size and stream
kernelParameters, null // Kernel- and extra parameters
);
cuCtxSynchronize();
// Allocate host output memory and copy the device output
// to the host.
float freq[] = new float[dataSize];
cuMemcpyDtoH(Pointer.to(freq), (CUdeviceptr)inputDataPointer, dataSize
* Sizeof.FLOAT);
And the kernel function is next:
extern "C"
__global__ void calcSpectrumSamples(float* complexData, int dataSize, int N, int pair) {
int i = threadIdx.x + blockIdx.x * blockDim.x;
if(i >= dataSize) return;
complexData[i] = complexData[i] * 2;
}
But when I'm trying to pass the pointer which points to the result of FFT (in device memory) to the multiplyOn2 method, it throws the exception on cuCtxSynchronize() call. Exception:
Exception in thread "main" jcuda.CudaException: CUDA_ERROR_UNKNOWN
at jcuda.driver.JCudaDriver.checkResult(JCudaDriver.java:263)
at jcuda.driver.JCudaDriver.cuCtxSynchronize(JCudaDriver.java:1709)
at com.ifntung.cufft.HilbertSpectrumTicksKernelInvoker.multiplyOn2(HilbertSpectrumTicksKernelInvoker.java:73)
at com.ifntung.cufft.FFTTransformer.main(FFTTransformer.java:123)
I was trying to do the same using Visual Studion C++ and there no problems with this. Could you please help me.
P.S.
I can solve this prolem, but I need to copy data from device memory to host memory and then copy back with creating new pointers every time before calling new cuda functions, which slows my program executing.
Where exactly does the error occurs at which line?
The Cuda error can also be a previous error.
Why do you use Pointer.to(inputDataPointer), you already have that device pointer. Now you pass a pointer to the device pointer to the device?
Pointer kernelParameters = Pointer.to(Pointer.to(inputDataPointer),
I also recommend to use "this" qualifier or any other marking to detect instance variables. I hate and refuse to look through code, especially as nested and long as your example if I cannot see which scope the variable in methods have trying to debug it by just reading it.
I don't wanna ask myself always where the hell comes this variable from.
If a complex code in a question at SO is not formatted properly I don't read it.

Intermediate image

I have a problem with intermediate image. The image is showing only once. After i move the image "line" is not showing anymore.
public void paintLine(Graphics g) {
if (line == null) {
line = new BufferedImage(1, height, BufferedImage.TYPE_INT_ARGB);
Graphics gImg = line.getGraphics();
float[] data = datas[index];
for (float f : data) {
float[] rgb = ColorMap.getPixelColor(f);
gImg.setColor(new Color(rgb[0], rgb[1], rgb[2]));
gImg.drawRect(0, (int)yPos--, 1, 1);
}
gImg.dispose();
}
xIncr++;
g.drawImage(line, (int)xPos - xIncr, (int)yPos, null);
graph.repaint();
}
This method is called in paintComponent ofJPanel.
If i recreate the image "line" each time, it is displaying properly with really poor performance.
Emm... I am not pretty sure owing to less information in your question but, as a rule, image may disappear because of doubleBuffered(false) option. So you need to set the double buffered option to true manually for your canvas. Code something like this
public class MyLabel extends JLabel{
public MyLabel()
{
this.setDoubleBuffered(true);
}
public void paintComponent(Graphics g)
{
this.paintLine(g);
}
public void paintLine(Graphics g) {
if (line == null) {
line = new BufferedImage(1, height, BufferedImage.TYPE_INT_ARGB);
Graphics gImg = line.getGraphics();
float[] data = datas[index];
for (float f : data) {
float[] rgb = ColorMap.getPixelColor(f);
gImg.setColor(new Color(rgb[0], rgb[1], rgb[2]));
gImg.drawRect(0, (int)yPos--, 1, 1);
}
//gImg.dispose();
}
xIncr++;
g.drawImage(line, (int)xPos - xIncr, (int)yPos, null);
graph.repaint();
}
}
Now I guess the conception is more clear
Good luck